Почему мне нужно ввести `./` перед выполнением программы в текущем каталоге?

Во время выполнения программы на языке Си, 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.

  • Или вы можете установить разрешения, щелкнув файл правой кнопкой мыши и выбрав Свойства:

    alt text

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

  1. Просто добавьте следующую строку в конец файла ~/.pam_environment:

    PATH DEFAULT=${PATH}:/path/to/programs

    Источник: Постоянные переменные среды

  2. Выйдите из системы и снова войдите в систему. Теперь вы сможете запускать a.out без ./ из любого каталога.

Если у вас есть другие программы в других каталогах, вы можете просто добавить их в приведенную выше строку. Однако я бы посоветовал, например, иметь один каталог под названием "myPrograms" и поместить в него все ваши программы.

Решение 2

Примечание: менять userName к вашему фактическому имени пользователя Ubuntu.

Что делать, если у вас есть другие программы, которые вы хотите запустить? И все они находятся в разных папках? Что ж, "более организованным" решением было бы создать папку с именем bin в вашем домашнем каталоге и добавьте символические ссылки (ярлыки) в эту папку. Вот как это делается:

  1. mkdir /home/userName/bin

    • Это приведет к созданию папки bin в вашем домашнем каталоге.
  2. ln -s /path/to/programs/a.out /home/userName/bin

    • Это создаст "символическую ссылку" (по сути, ярлык) вашего a.out программа в рамках bin.
  3. Выйдите из системы и снова войдите в систему. Теперь вы сможете запускать 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" свой путь к местоположению файла.

Связанный вопрос в Unix.SE Почему мы используем косую черту “./” для выполнения файла?

Канонический: command line - Why do we use "./" (dot slash) to execute a file in Linux/UNIX? - Unix & Linux Stack Exchange