Как установить текущий рабочий каталог в каталог скрипта?
Я пишу сценарий Bash. Мне нужен текущий рабочий каталог, чтобы всегда быть каталогом, в котором находится скрипт.
Поведение по умолчанию состоит в том, что текущий рабочий каталог в скрипте - это оболочка, из которой я его запускаю, но я не хочу этого поведения.
13 ответов
Попробуйте следующие простые однострочники:
Для всех UNIX/OSX/Linux
dir=$(cd -P -- "$(dirname -- "$0")" && pwd -P)
Примечание. Двойная тире (-) используется в командах для обозначения конца параметров команды, поэтому файлы, содержащие тире или другие специальные символы, не нарушают команду.
Для Linux, Mac и других *BSD:
cd $(dirname $(realpath $0))
С поддержкой пробелов:
cd "$(dirname "$(realpath "$0")")";
Замечания: realpath
должен быть установлен в самом популярном дистрибутиве Linux по умолчанию (например, Ubuntu), но в некоторых он может отсутствовать, поэтому его нужно установить.
В противном случае вы можете попробовать что-то подобное (он будет использовать первый существующий инструмент):
cd $(dirname $(readlink -f $0 || realpath $0))
Для Linux:
cd $(dirname $(readlink -f $0))
Использование GNU readlink на *BSD/Mac:
cd $(dirname $(greadlink -f $0))
Примечание: вам нужно иметь coreutils
установлен (например, 1. Установите Homebrew, 2. brew install coreutils
).
В баш
В bash вы можете использовать расширения параметров для достижения этой цели, например:
cd ${0%/*}
но это не работает, если скрипт запускается из той же директории.
В качестве альтернативы вы можете определить следующую функцию в bash:
realpath () {
[[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}
Эта функция принимает 1 аргумент. Если аргумент уже имеет абсолютный путь, выведите его как есть, иначе выведите $PWD
переменная + аргумент имени файла (без ./
префикс).
или вот версия взята из Debian .bashrc
файл:
function realpath()
{
f=$@
if [ -d "$f" ]; then
base=""
dir="$f"
else
base="/$(basename "$f")"
dir=$(dirname "$f")
fi
dir=$(cd "$dir" && /bin/pwd)
echo "$dir$base"
}
Связанные с:
Как определить текущий каталог, в котором я запускаю свой скрипт оболочки?
Надежный способ для bash-скрипта получить полный путь к себе?
Смотрите также:
Принятый ответ хорошо работает для сценариев, которые не были символическими ссылками в других местах, например, в $PATH
,
#!/bin/bash
cd "$(dirname "$0")"
Однако, если скрипт запускается по символической ссылке,
ln -sv ~/project/script.sh ~/bin/;
~/bin/script.sh
Это будет компакт-диск в ~/bin/
каталог, а не ~/project/
каталог, который, вероятно, сломает ваш сценарий, если цель cd
должен включать зависимости относительно ~/project/
Безопасный ответ по символической ссылке ниже:
#!/bin/bash
cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
readlink -f
Требуется для определения абсолютного пути к потенциально символически связанному файлу.
Кавычки необходимы для поддержки файловых путей, которые потенциально могут содержать пробелы (плохая практика, но небезопасно предполагать, что это не так)
Здесь много правильных ответов, но один, который, как правило, более полезен для меня (чтобы относительные пути сценария оставались предсказуемыми / работающими), - это использовать pushd / popd:
pushd "$(dirname ${BASH_SOURCE[0]})"
trap popd EXIT
# ./xyz, etc...
Это перенесет каталог исходного файла в стек навигации, тем самым изменив рабочий каталог, но затем, когда сценарий завершится (по любой причине, включая сбой),
trap
будет работать
popd
, восстанавливая текущий рабочий каталог скрипта.
Этот скрипт, кажется, работает для меня:
#!/bin/bash
mypath=`realpath $0`
cd `dirname $mypath`
pwd
Командная строка pwd отражает местоположение скрипта как текущего рабочего каталога, независимо от того, откуда я его запускаю.
Я беру это, и это работает.
#!/bin/bash
cd "$(dirname "$0")"
CUR_DIR=$(pwd)
Получить реальный путь к вашему сценарию
if [ -L $0 ] ; then
ME=$(readlink $0)
else
ME=$0
fi
DIR=$(dirname $ME)
(Это ответ на тот же мой вопрос здесь: получить имя каталога, в котором выполняется скрипт)
Большинство ответов либо не обрабатывают файлы, которые связаны символическими ссылками через относительный путь, не являются однострочными, либо не обрабатывают BSD (Mac). Решение, которое делает все три:
HERE=$(cd "$(dirname "$BASH_SOURCE")"; cd -P "$(dirname "$(readlink "$BASH_SOURCE" || echo .)")"; pwd)
Во-первых, cd к концепции каталога сценария в bash. Затем прочитайте ссылку на файл, чтобы увидеть, является ли это символической ссылкой (относительной или иной), и если да, перейдите в этот каталог. Если нет, перейдите в текущий каталог (необходимо, чтобы все было однострочным). Затем отобразите текущий каталог через
pwd
.
Вы могли бы добавить
--
аргументам cd и readlink, чтобы избежать проблем с каталогами, названными как options, но я не беспокоюсь для большинства целей.
Вы можете увидеть полное объяснение с иллюстрациями здесь:
https://www.binaryphile.com/bash/2020/01/12/determining-the-location-of-your-script-in-bash.html
Если вам просто нужно распечатать существующую рабочую директорию, тогда вы можете следовать этому.
$ vim test
#!/bin/bash
pwd
:wq to save the test file.
Дать разрешение на выполнение:
chmod u+x test
Затем выполните скрипт ./test
тогда вы можете увидеть настоящий рабочий каталог.