Я пытаюсь эмулировать процесс разрешения пути (см. Man-страницу path_resolution) в Unix-подобных системах.
Моя ОС Linux с ядром GNU 8.7.
Чтобы прояснить значение дополнительного трейлинга «/» в резолюции, я сделал следующие вещи в оболочке:
mkdir this_is_dir
ln -s this_is_dir this_is_link
rm this_is_link
Все было хорошо, потому что this_is_link является символической ссылкой, и я просто удалил ее. Но пока пытаюсь:
mkdir this_is_dir
ln -s this_is_dir this_is_link
rm this_is_link/
Это повторилось rm: cannot remove 'this_is_link/': Is a directory
Ну, после «/» последовала символическая ссылка, подумал я. Итак, я попробовал другую команду:rmdir this_is_link/
И вышел забавный результат: rmdir: failed to remove 'this_is_link/': Not a directory
Не то, что я ожидал. Поэтому я попросил моего друга подтвердить, можно ли получить такой же результат в его системе. У него была более низкая версия coreutils, чем у меня. И результат не был удивителен, независимо от того , rm
или rmdir 'this_is_link/'
, такая же ошибка Not a directory
происходит .
А другой друг только что опробовал его на своей Mac OS, результат: rm
=> 'Является ли каталог', rmdir
=> каталог успешно удален, ссылка осталась .
Есть ли какие-либо спецификации о точном поведении разрешения пути?
Ответы:
Спецификация POSIX / Single Unix указывает, что имя пути с косой чертой должно ссылаться на каталог (см. Базовые определения §4.11 разрешение пути ).
foo/
на самом деле определяется как эквивалентfoo/.
(для целей разрешения пути, а не при манипулировании именами файловbasename
иdirname
игнорирует завершающие косые черты). Большинство реализаций уважают это, но есть несколько исключений.Это объясняет поведение
rm this_is_link/
: это эквивалентно томуrm this_is_link/.
, где аргумент явно является каталогом.rmdir this_is_link/
Аналогично следует обратиться к каталогу. То, чего нет на вашей машине, является ошибкой в GNU coreutils. OSX ведет себя правильно здесь.источник
Мой дубль:
Кстати, разрешение пути очень мало связано с этим, просто кажется, что '' rm '' обрезает угол, а не (правильно) вызывает stat для аргумента (что и делает rmdir).
Приветствия.
источник
rm
вызывает stat (ну, собственно, newfstatat сAT_SYMLINK_NOFOLLOW
опцией) и отказывается продолжать, тогда как rmdir фактически вызывает rmdir (2), но получаетENOTDIR
.AT_SYMLINK_NOFOLLOW
будет препятствовать тому, чтобы он следовал по символической ссылке, поэтому rm должен удалить саму ссылку вместо вывода «Not a directory», что не соответствует обстоятельствам.stat
иstat -L
отличается только в том случае, если аргумент задан без завершающего слеша.rm
ведет себя правильно, аrmdir
не так. Трейлинг/
должен заставить их обрабатывать свои аргументы как каталог, в соответствии со стандартом POSIX. Смотрите мой ответ для ссылок .