Почему команда `find -type d -exec rmdir {} \;` выдает сообщение «Нет такого файла или каталога»

Почему команда `find -type d -exec rmdir {} \;` выдает сообщение «Нет такого файла или каталога»

В целях тестирования я создал следующие каталоги.

user@linux:~$ mkdir dir0{1..3}

user@linux:~$ ls -l
total 12K
drwxr-xr-x 2 user user 4.0K Mei  31 10:45 dir01
drwxr-xr-x 2 user user 4.0K Mei  31 10:45 dir02
drwxr-xr-x 2 user user 4.0K Mei  31 10:45 dir03
user@linux:~$ 

Затем я удалил его с помощьюfind -exec

user@linux:~$ find -type d -exec rmdir {} \;
rmdir: failed to remove '.': Invalid argument
find: ‘./dir02’: No such file or directory
find: ‘./dir01’: No such file or directory
find: ‘./dir03’: No such file or directory
user@linux:~$ 

Каталоги были удалены, я это проверил.

user@linux:~$ ls -l
total 0
user@linux:~$ 

У меня есть вопросы:

1) Я не понимаю, почему там были сообщения. Есть идеи, почему?

rmdir: failed to remove '.': Invalid argument
find: ‘./dir02’: No such file or directory

Я не вижу такой ошибки вrmdir

user@linux:~$ mkdir dir0{1..3}
user@linux:~$ 

user@linux:~$ ls -l
total 12K
drwxr-xr-x 2 user user 4.0K Mei  31 22:58 dir01
drwxr-xr-x 2 user user 4.0K Mei  31 22:58 dir02
drwxr-xr-x 2 user user 4.0K Mei  31 22:58 dir03
user@linux:~$ 

user@linux:~$ rmdir *
user@linux:~$ 

user@linux:~$ ls -l
total 0
user@linux:~$ 

2) Можно ли удалить эти сообщения?

решение1

Вы получаете эти ошибки "Нет такого файла или каталога", findпотому что findпытается войти в каталоги, которые он только что удалил. Он по умолчанию применит свои действия ко всем соответствующим вещам в каталоге, который он в данный момент посещает, прежде чем продолжить в подкаталогах.

Добавьте -depthк вызову , findчтобы выполнить findпоиск в глубину его путей поиска, что, в свою очередь, означает, что если вы выполните rmdirкоманду в каталоге, она уже посетит его и не будет пытаться посетить его снова.

-depthПри использовании по этой причине подразумевается опция ( -deleteв реализациях, findкоторые имеют -delete).

find . -depth -type d -exec rmdir {} \;

-depthявляется стандартной опцией для findкоммунального предприятия.

Обратите внимание, что это rmdirработает только с пустыми каталогами. Если у вас много непустых каталогов, команда выше выдаст много сообщений об ошибках.

Вместо этого, если вы findэто поддерживаете, используйте -empty:

find . -type d -empty -delete

Это приведет к удалению пустых каталогов.

С тем find, что не имеет нестандартных -deleteни -emtpy:

find . -depth -type d -exec sh -c '
    for dirpath do
        set -- "$dirpath"/*
        [ ! -e "$1" ] && rmdir "$dirpath"
    done' sh {} +

Это позволит проверить, пусты ли найденные каталоги, и если да, то они будут удалены.

Это длинный фрагмент кода, позволяющий избежать появления некоторых сообщений об ошибках из-за того, что каталоги не пустые, но любые сообщения об ошибках, которыеявляютсяпроизведённые, как мы надеемся, будут более интересными для просмотра, поскольку они, вероятно, будут ошибками "отказано в доступе". Перенаправление ошибок в /dev/nullпервую findкоманду наверху скрыло бы такие ошибки.

решение2

Предположительно, при использовании -exec ... \;конструкции find выполняет свою работу шаг за шагом:

  • пройтись по дереву каталогов, найдя записи, которые соответствуют -type d, и
  • запускайте rmdirпроверку таких записей сразу же после их обнаружения.

Это означает, что в вашем примере find будет искать dir01, запомнит его как каталог для последующего входа, затем выполнит rmdirего, а затем, при попытке рекурсивного перехода в dir01, потерпит неудачу, поскольку он больше не существует.

В этом случае запуск with -exec rmdir {} +должен помочь: будет выдан один вызов to rmdir dir01 dir02 dir03. Это избавит от последних трех сообщений об ошибках.

Сообщение об ошибке о .том, что, ну, ., текущий каталог действительно является каталогом, но не тем, который rmdirможно удалить, потому что он не пустой. Используйте , -min-depthчтобы прекратить его рассмотрение, сделав команду:

find -mindepth 1 -type d -exec rmdir {} +

Это не идеально; вложенные каталоги или большое количество совпадающих каталогов все еще могут приводить к выводу сообщений об ошибках, но это должно работать в простом случае из вопроса.

Связанный контент