Скорее всего, потому что удаление текущего рабочего каталога не будет хорошей идеей.
Алексей Магура
Согласовано - я как поведение по умолчанию, но это не соответствует, например, find . -print.
Мброши
@AlexejMagura, хотя я сочувствую, я не понимаю, почему удаление текущего каталога должно отличаться от удаления открытого файла. Объект останется в живых до тех пор, пока не будет создана ссылка на него, а затем соберет мусор. Вы можете сделать cd ..; rm -r dirс другой оболочкой с довольно четкой семантикой ...
Rmano
@Rmano это правда: это просто то, что я бы не стал делать в принципе: просто зайдите в каталог, а затем удалите текущий каталог. Я не совсем уверен, почему это так важно - хотя у меня были некоторые неудачи с текущим каталогом, который больше не существует, например, относительные пути больше не работают, но вы всегда можете выйти, используя абсолютный путь - но какая-то часть меня просто говорит, что это не очень хорошая идея в целом.
Алексей Магура
Ответы:
29
Члены об этом findutilsзнают , это для совместимости с * BSD:
Одна из причин, по которой мы пропускаем удаление "." для совместимости с * BSD, где это действие возникло.
NEWS в коде показывает Findutils источника , что они решили сохранить поведение:
#20802: If -delete fails, find's exit status will now be non-zero. However, find still skips trying to delete ".".
[ОБНОВИТЬ]
Поскольку этот вопрос стал одной из горячих тем, я углублюсь в исходный код FreeBSD и укажу более убедительную причину.
Как и должно быть: POSIX - король, плюс удаление текущего каталога может вызвать очень большие проблемы в зависимости от родительского приложения и того, что нет. Как, если бы текущий каталог был /var/logи вы запустили его как root, думая, что он удалит все подкаталоги, а также удалит текущий каталог?
Алексей Магура
1
Это хорошая теория, но на manстранице findнаписано: «Если удаление не удалось, выдается сообщение об ошибке». Почему не печатается ошибка?
Мброши
1
@AlexejMagura Удаление текущего каталога работает отлично в целом: mkdir foo && cd foo && rmdir $(pwd). Это удаление .(или ..), которое не работает.
Смысл удаления pathname / dot неясен, поскольку имя файла (каталога) в родительском каталоге, который нужно удалить, неясно, особенно при наличии нескольких ссылок на каталог.
Хотя 皞 皞 и Томас уже дали хорошие ответы на этот вопрос, я чувствую, что их ответы забыли объяснить, почему это поведение было реализовано в первую очередь.
В вашем find . -deleteпримере удаление текущего каталога звучит довольно логично и разумно. Но учтите:
$ find . -name marti\*
./martin
./martin.jpg
[..]
.Звучит ли удаление по- прежнему логично и нормально для вас?
Удаление непустого каталога является ошибкой - поэтому вы вряд ли потеряете данные с этим find(хотя вы могли бы с этим rm -r) - но в вашей оболочке текущий рабочий каталог будет установлен в каталог, который больше не существует, что приведет к некоторой путанице и удивительное поведение:
$ pwd
/home/martin/test
$ rm -r ../test
$ touch foo
touch: cannot touch 'foo': No such file or directory
Не удаляя текущий каталог, это просто хороший дизайн интерфейса и соответствует принципу наименьшего удивления.
find . -print
.cd ..; rm -r dir
с другой оболочкой с довольно четкой семантикой ...Ответы:
Члены об этом
findutils
знают , это для совместимости с * BSD:NEWS в коде показывает Findutils источника , что они решили сохранить поведение:
[ОБНОВИТЬ]
Поскольку этот вопрос стал одной из горячих тем, я углублюсь в исходный код FreeBSD и укажу более убедительную причину.
Давайте посмотрим на утилиту поиска исходного кода FreeBSD :
Как вы можете видеть, если он не отфильтровывает точку и точку-точку, то он достигнет
rmdir()
функции C, определенной в POSIXunistd.h
.Сделайте простой тест, rmdir с аргументом точка / точка-точка вернет -1:
Давайте посмотрим, как POSIX описывает rmdir :
Не было дано объяснения почему
shall fail
.Я нашел
rename
объяснить некоторые причины :Циклические пути файловой системы ?
Я просматриваю язык программирования C (2-е издание) и ищу тему каталога, неожиданно обнаружил, что код похож :
И комментарий!
«цикл навсегда» , это то же самое, что
rename
описать его как «циклические пути файловой системы» выше.Я немного модифицирую код и заставляю его работать в Kali Linux на основе этого ответа :
Посмотрим:
Это работает правильно, теперь, что, если я закомментирую
continue
инструкцию:Как видите, я должен использовать Ctrl+, Cчтобы убить эту программу с бесконечным циклом.
Каталог '..' читает свою первую запись '..' и зацикливается навсегда.
Вывод:
GNU
findutils
попробуйте совместить сfind
утилитой в * BSD .find
Утилита в * BSD внутренне используетrmdir
POSIX-совместимую функцию C, которую точка / точка-точка не позволяет.Причина
rmdir
запрета точка / точка-точка заключается в предотвращении циклических путей файловой системы.Язык программирования C, написанный K & R, показывает пример того, как точка / точка-точка приведет к созданию программы цикла навсегда.
источник
Потому что ваша
find
команда возвращается.
как результат. Со страницы информацииrm
:Таким образом,
find
в данном случае , похоже, просто придерживаться правил POSIX.источник
/var/log
и вы запустили его как root, думая, что он удалит все подкаталоги, а также удалит текущий каталог?man
страницеfind
написано: «Если удаление не удалось, выдается сообщение об ошибке». Почему не печатается ошибка?mkdir foo && cd foo && rmdir $(pwd)
. Это удаление.
(или..
), которое не работает.Системный вызов rmdir завершается неудачно с EINVAL, если последний компонент его пути аргумента
"."
. Он задокументирован по адресу http://pubs.opengroup.org/onlinepubs/009695399/functions/rmdir.html, и обоснование такого поведения:источник
Вызов
rmdir(".")
как системный вызов не сработал, когда я попробовал его, поэтому ни один инструмент более высокого уровня не может быть успешным.Вы должны удалить каталог через его настоящее имя, а не
.
псевдоним.источник
Хотя 皞 皞 и Томас уже дали хорошие ответы на этот вопрос, я чувствую, что их ответы забыли объяснить, почему это поведение было реализовано в первую очередь.
В вашем
find . -delete
примере удаление текущего каталога звучит довольно логично и разумно. Но учтите:.
Звучит ли удаление по- прежнему логично и нормально для вас?Удаление непустого каталога является ошибкой - поэтому вы вряд ли потеряете данные с этим
find
(хотя вы могли бы с этимrm -r
) - но в вашей оболочке текущий рабочий каталог будет установлен в каталог, который больше не существует, что приведет к некоторой путанице и удивительное поведение:Не удаляя текущий каталог, это просто хороший дизайн интерфейса и соответствует принципу наименьшего удивления.
источник