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

При запуске скриптов в Bash, я должен написать ./ в начале:

$ ./manage.py syncdb

Если я не, я получаю сообщение об ошибке:

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

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

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

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

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

9 ответов

Решение

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

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

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

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

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

РЕДАКТИРОВАТЬ

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

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

echo $PATH

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

PATH=$PATH:.

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

manage.py syncdb

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

Избегайте:

PATH=.:$PATH

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

Просто мои два цента.

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

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

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

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

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

./executable

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

executable

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

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

какой исполняемый файл

а также

whereis executable

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

Обоснование / Правило POSIX PATH

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

Во-первых, полная версия правила выглядит так:

  • если путь содержит / (например ./someprog, /bin/someprog, ./bin/someprog): Используется CWD, а PATH - нет.
  • если путь не содержит / (например someprog): Используется PATH, а CWD - нет.

Теперь предположим, что выполняется:

someprog

будет искать:

  • относительно CWD в первую очередь
  • относительно PATH после

Тогда, если вы хотите бежать /bin/someprog из вашего дистрибутива, и вы сделали:

someprog

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

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

Вот почему наличие относительных путей в вашем PATH - действительно плохая идея. Я смотрю на тебяnode_modules/bin.

И наоборот, предположим, что выполняется:

./someprog

Искал бы:

  • относительно PATH сначала
  • относительно CWD после

Тогда, если вы только что скачали скрипт someprog из репозитория git и вы хотите запустить его из CWD, вы никогда не будете уверены, что это именно та программа, которая будет запускаться, потому что, возможно, в вашем дистрибутиве есть:

/bin/someprog

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

Поэтому, опять же, вам придется всегда запускать локальные сценарии относительно CWD с полными путями, чтобы знать, что вы запускаете:

"$(pwd)/someprog"

что тоже было бы чрезвычайно раздражающим.

Еще одно правило, которое вы, возможно, захотите придумать:

относительные пути используют только PATH, абсолютные пути только CWD

но еще раз это заставляет пользователей всегда использовать абсолютные пути для сценариев, отличных от PATH, с "$(pwd)/someprog".

В / Правило поиска пути предлагает простое и запоминающееся решение проблемы about:

  • слэш: не использовать PATH
  • без косой черты: использовать только PATH

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

Иногда немного раздражает то, что вы не можете искать some/prog относительно PATH, но я не вижу более разумного решения этой проблемы.

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

Кроме того, (точка-косая черта) имела смысл для меня, когда у меня есть команда для дочерней папки 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

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

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

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

you are right "."  is for current directory.

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

Другие вопросы по тегам