В целях тестирования я создал следующие каталоги.
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 {} +
Это не идеально; вложенные каталоги или большое количество совпадающих каталогов все еще могут приводить к выводу сообщений об ошибках, но это должно работать в простом случае из вопроса.