Этот другой ответ хорош, но обсуждение в комментариях указывает, что более широкое объяснение может быть полезным.
Этот документ описывает, в какой последовательности POSIX-совместимая оболочка должна искать команды. Это очень общий, не самый простой способ понять. Вместо того, чтобы анализировать эту крайне абстрактную процедуру, давайте посмотрим, как действует реальная оболочка.
Если предположить,
- ваша
$PATH
выглядит так /usr/local/bin:/usr/bin:/bin
:; - ты в Баш;
- вы печатаете
ls
и нажимаете Enter; - нет
ls
псевдонима, который бы изменил команду на что-то другое ls
;
тогда Bash запустит первый существующий ls
объект из списка ниже. Именно этот список с учетом вашего случая.
ls
функция. ls
встроенный (обычно ls
это не встроенный в Bash; но так как Bash может динамически загружать новые встроенные команды, вы можете создать ls
встроенный). ls
исполняемый файл с полным путевым именем, хранящимся в хэш-таблице (это произойдет, если когда-то в прошлом ls
исполняемый файл был найден в соответствии со следующим пунктом и он все еще запоминается). ls
исполняемый файл из $PATH
. В вашем случае последовательность: /usr/local/bin/ls
/usr/bin/ls
/bin/ls
Обратите внимание, что нет ./ls
в процедуре; ни в какой момент ваш текущий рабочий каталог не принимается во внимание, особенно если он не сопоставлен с записями в $PATH
.
Теперь это утверждение
Linux не просматривает текущий каталог, чтобы узнать, доступна ли конкретная команда из этого каталога
только означает, что ./ls
в приведенном выше списке нет жестко заданного кода. Он появится в списке, если вы $PATH
содержали, .
но
по соображениям безопасности текущий каталог не находится в $PATH
переменной
Я объясню эти причины позже в ответе. Тем не менее, вы можете добавить .
в $PATH
свой собственный. В этом случае ./ls
появится в списке как 4.x запись. Сравните это с Windows, которая будет искать ls
в текущем рабочем каталоге, независимо от того, находится он в $PATH
или нет. Если бы Linux делал то же самое, то всегда была бы ./ls
запись, жестко закодированная где-то выше пункта 3 нашего списка.
Если ваш текущий рабочий каталог /usr/bin
и список ls
должен разрешить /usr/bin/ls
, то это технически тот же исполняемый файл, ./ls
но
- оболочка никогда не использует буквальный
./ls
путь, процедура возвращает /usr/bin/ls
; - тот факт, что вы находитесь, ничего не
/usr/bin
значит ; - Дело
/usr/bin
в том, много$PATH
значит .
Но если бы вы имели .
в качестве первой записи в вашем $PATH
тогда
- оболочка будет использовать буквальный
./ls
путь; - факт, в котором вы находитесь,
/usr/bin
будет много значить ; - Факт
/usr/bin
в том, $PATH
что ничего не значит .
В обоих случаях это один и тот же исполняемый файл, который запускается в конце дня, но оболочка попадает к нему по-разному.
Стоит также отметить, что утверждения типа «мой текущий рабочий каталог находится в моем $PATH
» или «Я в каталоге, который находится в моем $PATH
» не рассказывают всей истории. Они могут означать:
- "
/some/particular/directory
в моем, $PATH
и я в /some/particular/directory
данный момент"
или же
- «буквальная
.
запись в моем $PATH
».
Как показано, два случая различаются.
Похоже, вы ожидали, что вас ls
не найдут только потому, что вы оказались в его каталоге. Ну, это было бы неудобно, в то время как не было бы никакого преимущества безопасности вообще. Основная причина безопасности для не имеющих в .
качестве фиксированного шага в общей последовательности поиска команд и для не имеющих .
в $PATH
разъясняются в этом UNIX FAQ :
Рассмотрим, что происходит в случае, когда .
первая запись в PATH
. Предположим, что ваш текущий каталог является общедоступным для записи, например /tmp
. Если окажется, что программа, названная /tmp/ls
другим пользователем, осталась там, и вы ввели ls
(намереваясь, конечно, запустить обычную /bin/ls
программу), вместо этого будет запущена ваша оболочка ./ls
, программа другого пользователя. Излишне говорить, что результаты запуска неизвестной программы, как эта, могут вас удивить.
Там нет смысла запрещать /usr/bin/ls
только потому, что вы в /usr/bin
. Если ls
имеется вредоносное ПО, вы, вероятно, уже запустили его, работая в другом каталоге, или в конце концов запустите его, работая в другом каталоге.
ТЛ; др
Подводя итог, ls
в вашем примере работает, потому что это то, /usr/bin/ls
что найдено, а не ./ls
. Тот факт, что последний путь переходит в первый, не имеет значения, потому что последний путь не используется в первую очередь. Он не используется, потому что «Linux не смотрит в текущий каталог…» (то есть он не смотрит в .
). /usr/bin
Тем не менее, это выглядит, потому что это в вашем $PATH
.