
Выводит ли команда pwd
в скрипте оболочки каталог, в котором находится скрипт оболочки?
решение1
Здесь задействованы три независимых «каталога»:
- текущий рабочий каталог вашей текущей оболочки,
- текущий рабочий каталог скрипта оболочки и
- каталог, содержащий скрипт оболочки.
Чтобы продемонстрировать их независимость, вы можете написать скрипт оболочки, сохраненный в /tmp/pwd.sh, содержащий:
#!/bin/sh
pwd
cd /var
pwd
Затем вы можете изменить свой пароль (#1 выше) на /:
cd /
и выполните скрипт:
/tmp/pwd.sh
который начинается с демонстрации вашего существующего pwd (#1), затем меняет его на /var и показывает его снова (#2). Ни один из этих pwd
' не был "/tmp", каталогом, который содержит /tmp/pwd.sh (#3).
решение2
Текущий (или текущий) рабочий каталог
Возвращает ли команда pwd в скрипте оболочки каталог, в котором находится скрипт оболочки?
Нет.
Во-первых, по определению ни один скрипт оболочки или команда оболочки не возвращает ничего, кроме числового статуса выхода в диапазоне от 0 до 255. Это аксиома, но, как правило, это не то, что люди имеют в виду, когда задают подобные вопросы.
Во-вторых, pwd
это одновременно ивстроенная оболочка Bourneи стандартный системный двоичный файл. Любой из нихотпечаткилогический или физическийтекущий рабочий каталог, что обычно означает:
- Ваше местоположение в структуре каталогов при вызове скрипта или двоичного файла.
- Ваше текущее местоположение после смены рабочего каталога с помощьюCDили другие утилиты и встроенные функции, которые изменяют текущий рабочий каталог, такие как pushd или popd.
Если вам нужен каталог текущего скрипта, используйте dirname
утилиту, как описано в последнем разделе ниже.
Быстрый тестpwd
В качестве быстрого теста, чтобы увидеть, чтопвддействительно печатает, вы можете выполнить следующее:
# Create a shell script containing pwd.
cat <<-EOF > /tmp/test_pwd.sh
#!/bin/sh
pwd
EOF
# Make the script executable.
chmod 755 /tmp/test_pwd.sh
# Go somewhere on the filesystem, and call the test script.
cd /etc
/tmp/test_pwd.sh
Это выведет /etc
, а не /tmp
, потому что ваш текущий рабочий каталог в настоящее время /etc
. Это ожидаемое поведение.
Получение каталога, содержащего скрипт
Вы, вероятно, задаете этот вопрос, потому что хотите найти каталог текущего скрипта. В общем случае, вот быстрое и грубое решение:
#!/usr/bin/env bash
echo $(dirname "$0")
Это работает, потому что $0
обычно содержит имя пути, используемое для вызова исполняемого скрипта, а расширение оболочки использует dirname
утилиту для возврата пути, исключая часть имени файла. Вы можете сделать что-то похожее, но менее переносимое, с расширением параметра Bash "${0%/*}"
.
Конечно, это все очень сильное упрощение. Пожалуйста, прочтитеРуководство по Башу(особенно разделы о позиционных параметрах, специальных параметрах иBASH_ИСТОЧНИК) и страницы руководства для readlink
и realpath
для более полного понимания того, что такое пограничные случаи, которых существует несколько.
Однако в повседневном написании сценариев компонент каталога $0
достаточен, чтобы сказать вам, что вы хотите знать. Если вы делаете что-то достаточно сложное, где $0
не содержится информация, которая вам действительно нужна, и вам требуются более сложные конструкции, такие как:
echo $(dirname "$(realpath "$0")")
то вы, вероятно, усложняете себе жизнь больше, чем она должна быть.
решение3
pwd
возвращает 0, если только текущий рабочий каталог не может быть открыт.
mkdir /tmp/d; cd "$_"
pwd && pwd -P; echo "$?"
rmdir ../d
pwd && pwd -P; echo "$?"
/tmp/d
/tmp/d
0
/tmp/d
pwd: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
1
решение4
Он возвращает каталог, из которого он вызван/запущен, а не каталог, где находится скрипт!
Вот try.sh:
echo "The current working directory: $PWD"
Этот вывод сделает более понятным:
[akarpe@ADM-PROD-OMNI ~]$ sh try.sh
The current working directory: /mnt/home/akarpe
[akarpe@ADM-PROD-OMNI ~]$ sh try/try.sh
The current working directory: /mnt/home/akarpe
[akarpe@ADM-PROD-OMNI ~]$ sh ./try.sh
The current working directory: /mnt/home/akarpe
[akarpe@ADM-PROD-OMNI ~]$ sh ./try/try.sh
The current working directory: /mnt/home/akarpe
[akarpe@ADM-PROD-OMNI ~]$ cd try
[akarpe@ADM-PROD-OMNI try]$ sh ./try.sh
The current working directory: /mnt/home/akarpe/try
[akarpe@ADM-PROD-OMNI try]$ sh ../try.sh
The current working directory: /mnt/home/akarpe/try