Зачем вам нужно ./ (точка-косая черта) перед именем исполняемого файла или скрипта, чтобы запустить его в bash?

220

При запуске скриптов в bash мне нужно написать ./ в начале:

$ ./manage.py syncdb

Если я этого не сделаю, появится сообщение об ошибке:

$ manage.py syncdb
-bash: manage.py: command not found

В чем причина этого? Я думал, что . является псевдонимом для текущей папки, и поэтому эти два вызова должны быть эквивалентными.

Я также не понимаю, почему мне не нужно ./ при запуске приложений, таких как:

user:/home/user$ cd /usr/bin
user:/usr/bin$ git

(который работает без ./)

  • 2
    Это лучший документ по этому вопросу, с которым я когда-либо сталкивался: linfo.org/dot_slash.html
Теги:
command-line

9 ответов

257
Лучший ответ

Потому что в Unix, как правило, текущий каталог не находится в $PATH.

При вводе команды оболочка просматривает список каталогов, как указано переменной PATH. Текущий каталог отсутствует в этом списке.

Причиной отсутствия текущего каталога в этом списке является безопасность.

Скажем, что вы root и перейдите в другой каталог пользователя и введите sl вместо ls. Если текущий каталог находится в PATH, оболочка попытается выполнить программу sl в этом каталоге (так как нет другой программы sl). Эта программа sl может быть вредоносной.

Он работает с ./, потому что POSIX указывает, что имя команды, которое содержит /, будет использоваться как имя файла напрямую, подавляя поиск в $PATH. Вы могли бы использовать полный путь для того же самого эффекта, но ./ короче и легче писать.

ИЗМЕНИТЬ

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

  • 43
    Вам не нужно ничего набирать. Пользователь, возможно, только что загрузил вредоносный пакет, содержащий исполняемый файл ls .
  • 0
    Означает ли это, что . это не просто псевдоним для текущей папки, но на самом деле «расширяется» на весь путь? Не знал этого, спасибо ..
Показать ещё 6 комментариев
44

Когда bash интерпретирует командную строку, он ищет команды в местах, описанных в переменной окружения $PATH. Чтобы увидеть его, введите:

echo $PATH

У вас будет несколько путей, разделенных двоеточиями. Поскольку вы увидите, что текущий путь . обычно не находится в $PATH. Поэтому bash не может найти вашу команду, если она находится в текущем каталоге. Вы можете изменить его, если:

PATH=$PATH:.

Эта строка добавляет текущий каталог в $PATH, чтобы вы могли:

manage.py syncdb

Рекомендован не, так как он имеет проблемы с безопасностью, плюс вы можете иметь странное поведение, поскольку . зависит от того, в каком каталоге вы находитесь:)

Избегайте:

PATH=.:$PATH

Как вы можете "замаскировать" какую-то стандартную команду и открыть дверь для нарушения безопасности:)

Только мои два цента.

32

Ваш script, если в вашем домашнем каталоге не будет найден, когда оболочка увидит переменную среды $PATH, чтобы найти ваш script.

./ говорит: "Посмотрите в текущем каталоге для моего script, а не на все каталоги, указанные в $PATH".

4

Когда вы включаете '.' вы по существу предоставляете "полный путь" исполняемому файлу bash script, поэтому вашей оболочке не нужно проверять вашу переменную PATH. Без '.' ваша оболочка будет выглядеть в вашей переменной PATH (которую вы можете увидеть, запустив echo $PATH, чтобы увидеть, будет ли введенная вами команда проживает в любой из папок вашего PATH. Если это не так (как в случае с manage.py) он говорит, что не может найти файл. Считается, что плохая практика включает текущий каталог на вашем PATH, который здесь объясняется достаточно хорошо: http://www.faqs.org/faqs/unix-faq/faq/part2/section-13.html

1

У этого вопроса уже есть некоторые удивительные ответы, но я хотел добавить, что если ваш исполняемый файл находится в PATH, и вы получаете очень разные выходы при запуске

./executable

к тем, которые вы получите, если вы запустите

executable

(скажем, вы сталкиваетесь с сообщениями об ошибках с одним, а не с другим), тогда проблема может заключаться в том, что на вашем компьютере есть две разные версии исполняемого файла: одна на пути, а другая нет.

Проверьте это, запустив

который исполняемый

и

whereis executable

Он исправил мои проблемы... У меня было три версии исполняемого файла, только один из которых был правильно скомпилирован для среды.

1

В * nix, в отличие от Windows, текущий каталог обычно не находится в вашей переменной $PATH. Таким образом, текущий каталог не выполняется при выполнении команд. Вам не нужно ./ для запуска приложений, потому что эти приложения находятся в вашей $PATH; скорее всего, они находятся в /bin или /usr/bin.

0

У всех есть большой ответ на вопрос, и да, это применимо только при его запуске в текущем каталоге, если вы не включите абсолютный путь. См. Мои образцы ниже.

Кроме того, (точка-косая черта) имела смысл для меня, когда у меня есть команда в дочерней папке tmp2 (/tmp/tmp2), и она использует (двойная точка-косая черта).

ОБРАЗЕЦ:

[fifiip-172-31-17-12 tmp]$ ./StackO.sh

Hello Stack Overflow

[fifi@ip-172-31-17-12 tmp]$ /tmp/StackO.sh

Hello Stack Overflow

[fifi@ip-172-31-17-12 tmp]$ mkdir tmp2

[fifi@ip-172-31-17-12 tmp]$ cd tmp2/

[fifi@ip-172-31-17-12 tmp2]$ ../StackO.sh

Hello Stack Overflow
0

Когда script не находится в Пути, это необходимо для этого. Для получения дополнительной информации прочитайте http://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_01.html

  • 5
    К вашему сведению, в #bash на irc.freenode.org мы постоянно исправляем недоразумения, извлеченные людьми из TLDP (в частности, Advanced Bash Guide). Таким образом, направление туда людей ... может быть, не идеально. (Наша предпочтительная вводная документация - mywiki.wooledge.org/BashGuide )
-4

Существует разница между Current Directory и Working Directory, которую вы можете легко найти на google. По этой причине ваш manage.py syncdb не выполнит, как ожидалось.

Текущий каталог. Это каталог, из которого выполняется ваш shell или родительский процесс.

you are right "."  is for current directory.

В системе на базе UNIX, если у вас есть файл в /data/myfile.out, вы переходите к своему файлу через имена компонентов, которые разделены forward slash "/", поэтому если "." является вашим текущим каталогом, то если вы хотите получить доступ (выполнить в вашем случае), который находится внутри вашего текущего каталога, вам нужно будет сказать ./myexecutableFile.o. Если у вас был исполняемый файл в другой папке вашего текущего каталога, вы бы сделали что-то вроде этого ./myFiles/myexecutableFile.o. Надеюсь, у вас есть то, что я пытаюсь объяснить.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню