Во время выполнения программы на языке Си, a.out
, используя терминал Ubuntu, почему мне всегда нужно вводить ./
до a.out
, вместо того , чтобы просто писать a.out
? Есть ли решение для этого?
Когда вы вводите название программы, например a.out
система ищет файл по вашему ПУТИ. В моей системе ПУТЬ установлен на
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
Ваш, вероятно, похож. Чтобы проверить, введите echo $PATH
в терминале.
Система просматривает эти каталоги в указанном порядке, и если она не может их найти, программа выдает command not found
ошибка.
Добавление команды с помощью ./
эффективно говорит: "забудьте о ПУТИ, я хочу, чтобы вы искали только в текущем каталоге".
Аналогичным образом вы можете указать системе искать только в другом определенном местоположении, добавив к команде относительный или абсолютный путь, например:
../
означает в родительском каталоге, например ../hello
найдите hello в родительском каталоге.
./Debug/hello
: "ищите hello
в подкаталоге Debug моего текущего каталога."
или /bin/ls
: "ищите ls
в каталоге /bin
"
По умолчанию текущий каталог отсутствует в пути, поскольку он считается угрозой безопасности. Видеть Почему. не в пути по умолчанию? на суперпользователя, почему.
Можно добавить текущий каталог в свой ПУТЬ, но по причинам, указанным в связанном вопросе, я бы не рекомендовал этого делать.
Причина этого проста.
Предположим, у вас есть команда с тем же именем, что и приложение в текущем каталоге. Затем выполнение команды в командной оболочке вызовет ваше приложение вместо из встроенной команды. Это было бы проблемой безопасности, если не чем иным.
Требуя ./
для использования спереди оболочка знает, что вы хотите выполнить приложение с заданным именем, а не встроенную команду с этим именем.
./
выполняет файлы, которых нет в вашем $PATH
, скорее он выполняет файл в текущем каталоге (или другом через ./home/stefano/script.sh
). Теперь PATH - это переменная окружения, которая содержит все места, где bash может искать исполняемые программы, не имея полного (абсолютного) пути к ним.
Это разделение необходимо, чтобы избежать запуска неправильного файла. Т.е. если у вас есть файл с именем ls
в вашем домашнем каталоге, если он не находится на вашем ПУТИ, bash не сможет спутать его с реальным ls
. Переменная PATH также определяет порядок поиска:
- Когда вы выполняете команду или программа пытается выполнить
exec
системный вызов (специальный метод Ядра, как запускаются программы), система ищет файл, просматривая каждый из каталогов в вашем ПУТИ. Как только программа найдена, даже если она находится в нескольких каталогах, поиск прерывается и запускается первый найденный каталог.
Чтобы запустить файл, вам нужно будет установить исполняемый бит в разрешениях:
Поскольку вы уже находитесь в командной строке, вы можете просто ввести
chmod +x finename
.-
Или вы можете установить разрешения, щелкнув файл правой кнопкой мыши и выбрав Свойства:
Теперь вы можете скопировать файл в любой из каталогов в PATH, чтобы посмотреть, какие из них там находятся - и они устанавливаются для каждого пользователя - введите echo $PATH
.
stefano@3000-G530:~$ echo $PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
Если вы создаете исполняемый файл, cat
, и переместите его в /usr/local/sbin
, он запускается вместо надлежащего cat
, который находится в /bin
. Вы можете узнать, где находятся ваши файлы, используя type cat
и whereis cat
.
Зачем вам нужно печатать ./
перед выполнением программы?
В терминале всякий раз, когда вы вводите имя приложения, скажем gedit
, терминал будет искать в некоторых (предопределенных) каталогах, содержащих приложения (двоичные файлы приложений). Имена этих каталогов содержатся в переменной, называемой PATH
. Вы можете увидеть, что находится в этой переменной, выполнив echo $PATH
. Смотрите эти каталоги, разделенные :
? Это каталоги, в которых терминал будет выполнять поиск, если вы просто наберете gedit
, nautilus
, или a.out
. Как вы можете видеть, путь вашего a.out
программы там нет. Когда вы это сделаете ./a.out
, вы говорите терминалу "посмотрите в текущем каталоге и запустите a.out
, и не ходи заглядывать в PATH
.
Решение 1
Если вы не хотите вводить ./
каждый раз вам нужно будет добавлять a.out
каталог в $PATH
. В следующих инструкциях я предположу, что путь к a.out
является /path/to/programs/
, но вы должны изменить его на свой фактический путь.
-
Просто добавьте следующую строку в конец файла
~/.pam_environment
:PATH DEFAULT=${PATH}:/path/to/programs
Источник: Постоянные переменные среды
Выйдите из системы и снова войдите в систему. Теперь вы сможете запускать
a.out
без./
из любого каталога.
Если у вас есть другие программы в других каталогах, вы можете просто добавить их в приведенную выше строку. Однако я бы посоветовал, например, иметь один каталог под названием "myPrograms" и поместить в него все ваши программы.
Решение 2
Примечание: менять
userName
к вашему фактическому имени пользователя Ubuntu.
Что делать, если у вас есть другие программы, которые вы хотите запустить? И все они находятся в разных папках? Что ж, "более организованным" решением было бы создать папку с именем bin
в вашем домашнем каталоге и добавьте символические ссылки (ярлыки) в эту папку. Вот как это делается:
-
mkdir /home/userName/bin
- Это приведет к созданию папки
bin
в вашем домашнем каталоге.
- Это приведет к созданию папки
-
ln -s /path/to/programs/a.out /home/userName/bin
- Это создаст "символическую ссылку" (по сути, ярлык) вашего
a.out
программа в рамкахbin
.
- Это создаст "символическую ссылку" (по сути, ярлык) вашего
Выйдите из системы и снова войдите в систему. Теперь вы сможете запускать
a.out
без./
из любого каталога.
Теперь, всякий раз, когда у вас есть другая программа в другом месте, скажем, программа b.in
на вашем рабочем столе все, что вам нужно сделать, это: ln -s /home/userName/Desktop/b.in /home/userName/bin
, и тогда вы сможете запустить его без ./
также.
Примечание: благодаря Комментарий @Joe's, когда вы делаете резервные копии, символические ссылки должны обрабатываться особым образом. По умолчанию,
rsync
не обрабатывает их вообще, поэтому, когда вы восстанавливаете, их там нет.
Как отметил Джордж в своем ответе, это поможет вам отметить, что ваш проведение файл в текущем рабочем каталоге (pwd
).
Я помню, как давным-давно задавал этот вопрос своему старшему, он сказал, что я должен добавить .
на мой путь, чтобы, когда я сделаю a.out
он просматривает текущий каталог и выполняет его. В этом случае мне не нужно делать ./a.out
.
Но лично я бы не рекомендовал этого делать. Со мной этого никогда не случалось, но если вы находитесь в чужом сетевом каталоге или что-то в этом роде, и вредоносный исполняемый файл называется ls
существует там, то, имея .
на вашем пути - это очень плохая идея. Не то чтобы вы очень часто сталкивались с этой проблемой, просто говорю.
В дополнение к другим ответам, вот существенная часть из man bash
что хорошо объясняет это:
ВЫПОЛНЕНИЕ КОМАНДЫ После разделения команды на слова, если в результате получается простая команда и необязательный список аргументов, выполняются следующие действия. Если имя команды не содержит косых черт, оболочка попытается найти ее. Если существует функция оболочки с таким именем, эта функция вызывается, как описано выше в разделе ФУНКЦИИ. Если имя не соответствует функции, оболочка ищет ее в списке встроенных функций оболочки. Если найдено совпадение, вызывается этот встроенный компонент. Если имя не является ни функцией оболочки, ни встроенным и не содержит косых черт, bash ищет в каждом элементе ПУТИ каталог, содержащий исполняемый файл с таким именем.
'./' имеет смысл, когда вы запускаете программу, которая известна вам и специфична, например, вашу собственную. Эта программа должна присутствовать в вашем текущем каталоге. './' не имеет смысла, когда вы выполняете стандартную команду, которая находится где-то в $PATH.Команда "какая команда для запуска" сообщает вам, где находится команда для запуска в $PATH.
$ gcc hello.c -o /path/to/someplace/hello
создаст исполняемый файл в некотором месте. Если это местоположение находится на вашем пути, вы сможете запустить файл. Вы можете написать это в скрипте, если хотите создать метку для действия "скомпилируйте этот исходный код с помощью gcc и поместите исполняемый файл в какое-нибудь место, которое находится на вашем пути".
Я бы посоветовал вам создать новый каталог с именем "testbin" или что-то в этом роде и поместить его в свой путь, чтобы сохранить существующие каталоги path чистыми.
./
устраняет ненужный поиск пути. ./
принудительный поиск только в текущем каталоге. Если мы не дадим ./
затем он будет искать различные пути, установленные в системе, например /usr/bin
, /usr/sbin/
и т.д.
"./" означает, что вы хотите запустить файл в текущем каталоге, это ярлык для ввода полного пути, например:
[root@server ~]#/path/to/file/file.pl
это то же самое, что и :
[root@server file]#./file.pl
в предыдущем примере вы прошли через каталог и его вспомогательные каталоги к местоположению файла и использовали "./" для запуска файла в текущем каталоге.
тот, что был до этого "[root@server ~]#/path/to/file/file.pl" также выполнит файл, если вы нажмете на "cd" свой путь к местоположению файла.