Чому мені потрібно ввести `. /` Перед виконанням програми в поточному каталозі?


92

Виконуючи програму C a.out, використовуючи термінал Ubuntu, чому мені завжди потрібно вводити ./раніше a.out, а не просто писати a.out? Чи є для цього рішення?




Відповіді:


119

Коли ви вводите назву такої програми, як a.outсистема шукає файл у вашому PATH. У моїй системі встановлено значення PATH

/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помилку.

Попереджуючи команду, ./ефективно пише: "забудь про PATH, я хочу, щоб ти дивився лише в поточному каталозі".

Аналогічно ви можете сказати системі шукати лише в іншому конкретному місці, попередньо додавши команду до відносного або абсолютного шляху, такого як:

../засоби в батьківському каталозі, наприклад, ../helloшукайте привіт у батьківському каталозі.

./Debug/hello: "шукати helloу підкаталозі налагодження мого поточного каталогу."

або /bin/ls: "шукати lsв каталозі /bin"

За замовчуванням поточний каталог не стоїть на шляху, оскільки він вважається ризиком безпеки. Дивіться, чому так. не в шляху за замовчуванням? на Superuser чому.

Можна додати поточний каталог до вашого PATH, але з причин, наведених у пов'язаному питанні, я б не рекомендував його.


25
Це. +1 Не додайте .до своїх PATH(як це підказують інші 2 відповіді) через ризик безпеки, зазначений у цій відповіді.
День

8
Можливо, варто також зазначити, що тут немає нічого особливого ., ви можете використовувати повний або відносний шлях до виконуваного файлу, наприклад, /home/user/foo/a.outабо./build/a.out
tobyodavies

@tobyodavies; Насправді .це особливе, оскільки це означає "мій поточний каталог", тому може бути будь-яка директорія, яку користувач знаходить у них з привілеями для читання та виконання. Це потенційно небезпечніше, ніж додавання конкретного повністю кваліфікованого шляху.
Уоррен Хілл

@WarrenHill, коли ви розглядаєте, як додати його до свого шляху, так, це зовсім інше. Однак з точки зору синтаксису Баш, .не має особливого статусу, це просто шлях , який міг би так само добре почати з /і ./blahбуде працювати так само добре catабо grepяк Баш рядку.
tobyodavies

@tobyodavies: Гаразд Я змінив свою відповідь, щоб включити вашу думку.
Warren Hill

24

Причина цього проста.

Припустимо, у вас є команда з тим самим іменем, що і програма у поточному каталозі. Потім запуск команди в оболонці викликає ваш додаток замість вбудованої команди. Це було б проблемою безпеки, якщо нічого іншого.

Вимагаючи ./використання спереду, оболонка знає, що ви хочете виконати програму із заданим іменем, а не вбудованою командою з цим ім'ям.


1
ваше пояснення вводить в оману, є різниця між вбудованими командами в оболонці та виконуваними файлами, доступними через змінну PATH. Насправді ваша відповідь, чим більше я читаю, тим вона виявляється неправильнішою.
Ахмед Масуд

16

./виконує файли, яких немає у вашому $PATH, скоріше він виконує файл у поточному каталозі (або іншому через ./home/stefano/script.sh). Тепер PATH - це змінна середовище, яка містить усі місця, де bash може шукати виконувані програми, не маючи повного (абсолютного) шляху до них.

Ця відокремлення потрібна, щоб уникнути запуску неправильного файлу. Тобто, якщо lsу вашому домашньому каталозі є файл, який викликається , він не перебуває у вашому PATH, не дозволить Bash переплутати його з реальним ls. Змінна PATH також визначає порядок пошуку:

  • Коли ви запускаєте команду або програма намагається здійснити execсистемний виклик (спеціальний метод ядра, як запускаються програми), система шукає файл, переглядаючи кожен із каталогів вашої PATH. Як тільки програма знайдена, навіть якщо вона знаходиться в декількох каталогах, пошук переривається і перший знайдений запускається.

Щоб запустити файл, вам потрібно встановити виконавчий біт у дозволах:

  • Оскільки ви вже в командному рядку, ви можете просто ввести chmod +x finename.

  • Або ви можете встановити дозволи, клацнувши правою кнопкою миші файл і вибравши Властивості :

    alt текст

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


2
Варто зазначити одне: його питання, схоже, вказує на те, що він щось склав і зв'язав gcc, що автоматично встановлює біт виконання.
Натан Осман

12

Чому потрібно вводити ./перед виконанням програми?

У терміналі щоразу, коли ви вводите назву програми, скажімо 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, і ви зможете запустити її і без цього ./.

Примітка: завдяки коментарю @ Джо , коли ви робите резервні копії, символічні посилання потрібно обробляти спеціально. За замовчуванням їх rsyncвзагалі не обробляє, тому при відновленні їх там немає.


1
Це зручна хитрість, якщо вона використовується економно. Багато використовуючи це, ваша система робить те, чого не чекав би хтось інший. Крім того, коли ви робите резервні копії, символьні посилання повинні бути оброблені спеціально. За замовчуванням rsync взагалі не обробляє їх, тому при відновленні їх там немає.
Джо

1

Як зазначив Джордж у своїй відповіді, це допомагає вам зазначити, що ваше виконання файлу в поточному робочому каталозі ( pwd).

Я пам'ятаю, як давно дав це питання своєму старшому, він сказав, що я повинен додати .свій шлях, щоб коли я a.outце робив, він виглядав у поточному каталозі та виконує це. У цьому випадку мені не потрібно робити ./a.out.

Але особисто я рекомендував би проти цього. Зі мною цього не бувало, але якщо ви перебуваєте в каталозі чужорідних мереж або щось подібне, а шкідливий виконуваний файл, який називається, lsіснує там, то мати .на своєму шляху дуже погана ідея. Не те, що ви будете стикатися з цією проблемою дуже часто, просто кажучи.


Ок, Стефано прийняв свою відповідь, щоб містити цю інформацію :)
Шрікант Шарат

3
Я повністю згоден з не додаючи .до $PATH. Дуже небезпечна ідея.
Натан Осман

1

Окрім інших відповідей, ось істотна частина, з man bashякої це добре пояснюється:

ВИКОНАННЯ ВИКОНАННЯ
       Після розбиття команди на слова, якщо це призводить до простого
       команда та необов'язковий список аргументів, такі дії
       прийнято.

       Якщо ім'я команди не містить косої риски, оболонка намагається знайти
       це. Якщо існує функція оболонки за цим ім'ям, ця функція є
       викликається як описано вище у ФУНКЦІЙ. Якщо назва не відповідає а
       Функція, оболонка шукає її у списку вбудованих оболонок. Якщо
       знайдено відповідність, що викликається вбудований файл.

       Якщо назва не є ні функцією оболонки, ні вбудованою, і не містить
       косої риски, bash шукає кожен елемент PATH для пошуку каталогу -
       заклик виконуваного файлу під цим іменем.

0

"./" має сенс, коли ви запускаєте відому вам та конкретну програму, наприклад, власну. Ця програма повинна бути присутня у вашому поточному каталозі. "./" не має сенсу, коли ви запускаєте стандартну команду, яка знаходиться десь у $ PATH. Команда "котра команда для запуску" повідомляє, де знаходиться команда для запуску в $ PATH.


0
$ gcc hello.c -o /path/to/someplace/hello

створить виконуваний файл у якомусь місці. Якщо це місце знаходиться на вашому шляху, ви зможете запустити файл. Ви можете скопіювати це, якщо ви хочете створити мітку для дії "складіть цей вихідний код за допомогою gcc та розмістіть виконуваний файл у певному місці, яке знаходиться на вашому шляху".

Я б запропонував вам створити новий каталог під назвою "testbin" або щось подібне і поставити його на свій шлях, щоб зберегти існуючі каталоги шляху.


0

./виключає непотрібний пошук шляху. ./змусити шукати лише в поточному каталозі. Якщо ми не дамо, ./то він буде шукати різні шляхи, встановлені в системі, наприклад /usr/bin, /usr/sbin/і т.д.


0

"./" означає, що ви хочете виконати файл у поточному каталозі його ярлик для введення всього шляху, наприклад:

[root@server ~]#/path/to/file/file.pl

те саме, що:

[root@server file]#./file.pl

у попередньому прикладі ви перейшли через каталог та його довідники до місця розташування файлу та використали "./" для запуску файлу у поточному каталозі.

той, що передує, " [root @ server ~] # / path / to / file / file.pl " також виконає файл, якщо ви лінуєтеся "cd" пройти до місця розташування файлу.


-4

Це дуже просто і має безліч застосувань.

  1. Коли буде встановлено кілька версій однієї програми, вона буде доступна різним шляхом, але в ній можна створити м'яке посилання на ваш двійковий файл /usr/bin. Наприклад, встановлено Python 2.7, Python 2.6, але / usr / bin / python -> python2.7 / usr / local / bin / python -> python2.6

Якщо ви знаходитесь у шляху /usr/local/binта виконує Python, він завжди виконуватиме Python 2.7. Визначення .візьме виконуваний файл поточної папки.

  1. .- завжди представляє виконання з поточного каталогу. І ..завжди означає виконання з попереднього каталогу.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.