Зачем вам нужно./ (точка-косая черта) перед именем исполняемого файла или скрипта, чтобы запустить его в 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
, Надеюсь, вы получили то, что я пытаюсь объяснить.