Unix shell script выяснит, в каком каталоге находится файл скрипта? - PullRequest
420 голосов
/ 28 октября 2008

В основном мне нужно запустить скрипт с путями, относящимися к расположению файла сценария оболочки, как я могу изменить текущий каталог на тот же каталог, где находится файл сценария?

Ответы [ 16 ]

480 голосов
/ 28 октября 2008

В Bash вы должны получить то, что вам нужно, вот так:

#!/usr/bin/env bash

BASEDIR=$(dirname "$0")
echo "$BASEDIR"
351 голосов
/ 28 октября 2009

Оригинальный пост содержит решение (игнорируйте ответы, они не добавляют ничего полезного). Интересная работа выполняется упомянутой unix-командой readlink с опцией -f. Работает, когда скрипт вызывается как по абсолютному, так и по относительному пути.

Для баш, ш, кш:

#!/bin/bash 
# Absolute path to this script, e.g. /home/user/bin/foo.sh
SCRIPT=$(readlink -f "$0")
# Absolute path this script is in, thus /home/user/bin
SCRIPTPATH=$(dirname "$SCRIPT")
echo $SCRIPTPATH

Для tcsh, csh:

#!/bin/tcsh
# Absolute path to this script, e.g. /home/user/bin/foo.csh
set SCRIPT=`readlink -f "$0"`
# Absolute path this script is in, thus /home/user/bin
set SCRIPTPATH=`dirname "$SCRIPT"`
echo $SCRIPTPATH

Смотри также: https://stackoverflow.com/a/246128/59087

47 голосов
/ 05 апреля 2013

Более ранний комментарий к ответу сказал это, но его легко пропустить среди других ответов.

При использовании bash:

echo this file: "$BASH_SOURCE"
echo this dir: "$(dirname "$BASH_SOURCE")"

Справочное руководство Bash, 5.2 Переменные Bash

38 голосов
/ 28 октября 2008

Если вы используете bash

#!/bin/bash

current_dir=$(pwd)
script_dir=$(dirname $0)

echo $current_dir
echo $script_dir

Этот сценарий должен напечатать каталог, в котором вы находитесь, а затем каталог, в котором находится сценарий. Например, при вызове его из / со сценарием в /home/mez/ он выводит

/
/home/mez

Помните, что при назначении переменных из выходных данных команды оберните команду в $( и ) - иначе вы не получите желаемого результата.

31 голосов
/ 18 марта 2010

Если вы используете bash ....

#!/bin/bash

pushd $(dirname "${0}") > /dev/null
basedir=$(pwd -L)
# Use "pwd -P" for the path without links. man bash for more info.
popd > /dev/null

echo "${basedir}"
17 голосов
/ 06 июня 2011

Как предполагает Марко:

BASEDIR=$(dirname $0)
echo $BASEDIR

Это работает, если вы не выполните скрипт из той же директории, где находится скрипт, в этом случае вы получите значение '.'

Чтобы обойти эту проблему, используйте:

current_dir=$(pwd)
script_dir=$(dirname $0)

if [ $script_dir = '.' ]
then
script_dir="$current_dir"
fi

Теперь вы можете использовать переменную current_dir по всему сценарию, чтобы ссылаться на каталог сценария. Однако это может все еще иметь проблему символической ссылки.

15 голосов
/ 20 июня 2017

Лучший ответ на этот вопрос был дан здесь:
Получение исходного каталога скрипта Bash из

А есть:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

Одна строка, которая даст вам полное имя каталога скрипта независимо от того, откуда он вызывается.

Чтобы понять, как это работает, вы можете выполнить следующий скрипт:

#!/bin/bash

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  TARGET="$(readlink "$SOURCE")"
  if [[ $TARGET == /* ]]; then
    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
    SOURCE="$TARGET"
  else
    DIR="$( dirname "$SOURCE" )"
    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
    SOURCE="$DIR/$TARGET" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
  fi
done
echo "SOURCE is '$SOURCE'"
RDIR="$( dirname "$SOURCE" )"
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
if [ "$DIR" != "$RDIR" ]; then
  echo "DIR '$RDIR' resolves to '$DIR'"
fi
echo "DIR is '$DIR'"
13 голосов
/ 14 января 2011
cd $(dirname $(readlink -f $0))
8 голосов
/ 11 мая 2017

Давайте сделаем это POSIX oneliner:

a="/$0"; a=${a%/*}; a=${a#/}; a=${a:-.}; BASEDIR=$(cd "$a"; pwd)

Протестировано на многих Bourne-совместимых оболочках, включая BSD.

Насколько я знаю, я являюсь автором и выложил его в общественное достояние. Для получения дополнительной информации см .: https://www.jasan.tk/posts/2017-05-11-posix_shell_dirname_replacement/

7 голосов
/ 12 сентября 2018
BASE_DIR="$(cd "$(dirname "$0")"; pwd)";
echo "BASE_DIR => $BASE_DIR"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...