Есть ли разница между путями «file» и «./file»?

12

Как говорится в заголовке, есть ли разница для файловых систем * NIX? например ls fileиls ./file

Сергей Алаев
источник
1
Вы можете спросить unix.stackexchange.com - ответы на все вопросы содержат хорошую информацию, но ни один из них не похож на ответ.
Роб Старлинг

Ответы:

14

Я не в восторге от объяснения SmallLoanOf1M. Это технически правильно, но отвечает таким образом, который не соответствует примеру использования в вопросе.

Итак, в качестве примера, здесь есть одно важное отличие между этими двумя вопросами: «файл» и «./file»

Что, если файл назван с символом, который анализируется оболочкой? Особенно в отношении символов, интерпретируемых командой.

В частности, символ «тире»: «-». Но другие символы имеют значение для оболочки.

Пример. Мой файл был назван "-dingle"

Попробуйте перечислить файл:

ls -dingle
# ls -dingle
ls: invalid option -- 'e'

Еще хуже, что, если файл был назван " -rf rmbomb *"? Теперь попробуйте удалить его

rm "-rf rmbomb *"

Я даже не собираюсь приводить этот пример, но, надеюсь, вы поняли идею.

Итак, как вы перечисляете файл, начинающийся с тире? Используйте ./спереди.

# ls ./-dingle
./-dingle

То же самое для rm

JDS
источник
Это правильный способ обработки некоторых файлов с нечетными именами, и мой ответ не рассматривал такие файлы. Вместо этого можно также использовать литерал во всех приведенных выше примерах в форме обратной косой черты, предшествующей нечетным символам, включая пробелы, указанные выше. Примером этого может быть так: ls \-dingleили ls \-rf\ rmbomb\ \*. Это может быть хорошим способом обеспечения того, чтобы любой заданный набор команд был по меньшей мере непротиворечивым, так как указание ./перед именем не будет экранировать символы после ./.
Спулер
2
Бывает, что, поскольку экранированные символы экранируются оболочкой, а не командой, а параметры анализируются командой, экранирование или цитирование - ничего полезного не делает.
Деви Морган
2
Вы говорите так, будто на rm "-rf rmbomb *"самом деле делаете что-то плохое, вместо того, чтобы просто rmнапечатать ошибку. Это опасно, только если вы забыли процитировать имя файла, поэтому происходит разделение слов. (Особенно в сценарии оболочки, где вы запускаете rm $fileвместо rm "$file". Но в этом случае, *расширение не будет расширяться, потому что расширение glob не происходит в содержимом раскрытия переменных. Если вы этого хотите, вам нужен eval.) В любом случае, если ваш сценарий разделяет имена файлов перед передачей в rm, я бы сделал файл с именем space -rf .или как-то еще, так что rm ./$iэто не поможет.
Питер Кордес
1
Кстати, фактическое сообщение об ошибке - rm: invalid option -- ' 'от того, когда оно пытается интерпретировать пространство после -rfкак односимвольный переключатель, потому что это часть того же аргумента. (И да, я запустил это в пустом каталоге на тот случай, если я что-то упустил, и это было действительно опасно: P)
Питер Кордес
2
@PeterCordes: разделение слов и подстановка происходит в результатах раскрытия переменных без подстановки и подстановки команд, если они не подавлены IFS=''и -fсоответственно. Более редким примером является то, что awkоперанд (отличный от первого операнда, являющегося сценарием) рассматривает форму foo=barкак назначение для выполнения, но ./foo=barкак файл для чтения.
dave_thompson_085
7

Да.

В fileкомандной строке BASH будет искать переменную окружения $ PATH для файла с таким именем. Если файл не находится в каталоге в переменной $ PATH, он не будет найден.

.означает текущий каталог. ./означает в текущем каталоге, в относительном выражении. Это эквивалентно тому, чтобы сказать что-то вроде /home/sheogorath/shivering/isles.imgпри вызове ./isles.imgво время работы в /home/sheogorath/shivering/каталоге.

Как таковой, он обычно используется для выполнения файлов в вашем рабочем каталоге "на месте".

РЕДАКТИРОВАТЬ: В вашем примере lsвызывается из оболочки и найти с помощью переменной пути. Его аргумент будет обработан в вашем рабочем каталоге, что бы это ни было. Поскольку это значение по умолчанию для ls, вы не увидите никакой разницы между указанием fileи явным указанием, ./fileпоскольку они оба указывают на ваш текущий каталог.

Не все команды будут принимать пути к файлам в рабочем каталоге, а некоторые ожидают, что вы будете указывать файлы в каталоге, который они сами предварительно задают в конфигурации. Среди команд, которые принимают файлы в качестве аргументов, эти команды встречаются реже

шпульницы
источник
1
Это bash, но мне было интересно узнать о разрешении пути в целом
Сергей Алаев
1
Так работает любая оболочка, о которой я когда-либо слышал. BASH является просто наиболее часто используемым.
Spooler
4
$ PATH относится только к командам и не имеет ничего общего с аргументами имени файла, которые следуют за командой, такой как lsупомянутая в исходном вопросе. То есть чем больше разница между refferencing на относительный путь ( по отношению к текущему рабочему каталогу) Т.е. ../../dir/filenameи абсолютный путь /path/to/dir/filename
HBruijn
1
+1 за Шеогората ... и правильный ответ.
Кори Огберн
1
Если они являются аргументами команды, которая пытается найти файлы в рабочем каталоге по умолчанию, они будут такими же. Таким образом, поскольку lsони всегда будут одним и тем же путем, один указан более явно, чем другой. Не все команды ведут себя таким образом при обработке аргументов, но большинство так и делают.
Спулер