Предполагая, что у вас нет странных имен файлов:
find . \! -name '.' -type d -prune |
grep -v -f ids.txt |
xargs echo rm -rf
Это должно работать с любым POSIX find / grep / xargs . Удалите echo
, когда вы будете удовлетворены, удалите -v
, чтобы удалить соответствующие каталоги.
- find - поиск файлов
\! -name '.'
- файл не называется «.», поэтому он не включает каталог root (вам может потребоваться адаптировать его, если вы запускаете его из другого каталога) -type d
- выбрать только каталоги -prune
- после обнаружения не вводите каталог, просто напечатайте его
- grep - фильтр
-f ids.txt
- загрузить шаблоны из файла ids.txt -v
- вернуть строки, которые не совпадают
- xargs - запустить команду с аргументами из стандартного ввода
Примечание: если вы запустите find из другого каталога, вам нужно будет изменить -name
, чтобы он соответствовал базовому каталогу, в котором находятся ваши каталоги. Пример:
$ find ./60476598/ \! -name '.' -type d -prune
./60476598/
$ find ./60476598/ \! -name '60476598' -type d -prune
./60476598/chain_asd123
./60476598/hello?_1effaj
$ find /home/sorin/tmp/60476598/ \! -name '60476598' -type d -prune
/home/sorin/tmp/60476598/chain_asd123
/home/sorin/tmp/60476598/hello?_1effaj
В этом случае моя тестовая установка находится в каталоге с именем 60476598 (идентификатор вопроса). Если вы не примете это во внимание, вы увидите, что он вернет только базовый каталог, но если вы измените -name '.'
на -name '60476598'
, он будет работать как положено. Вы должны использовать только имя каталога, а не весь путь.
Несколько лучший подход , если у вас есть набор утилит, поддерживающих разделение записей на ноль:
find . \! -name '.' -type d -prune -print0 |
grep -v -z -f ids.txt |
xargs --null echo rm -rf
В этом случае -print0
указывает find
выводить результаты, разделенные нулевым символом, -z
сообщает grep
, что строки разделяются нулевым символом, а --null
сообщает xargs
что входные строки разделены нулем. Эти параметры не требуются для совместимости с POSIX, однако они доступны для вариантов этих инструментов GNU.
В чем разница?
Предположим, у вас есть каталог с Новая строка в ее имени:
ls -1la
total 28
drwxr-xr-x 6 sorin pi 4096 Mar 1 18:18 .
drwxr-xr-x 31 sorin pi 4096 Mar 1 17:26 ..
drwxr-xr-x 2 sorin pi 4096 Mar 1 17:26 chain_asd123
drwxr-xr-x 2 sorin pi 4096 Mar 1 17:26 hello_1afadf
drwxr-xr-x 2 sorin pi 4096 Mar 1 18:18 hello_1effaj
drwxr-xr-x 2 sorin pi 4096 Mar 1 18:17 hello?_1effaj
-rw-r--r-- 1 sorin pi 29 Mar 1 17:28 ids.txt
В этом случае привет? _1effaj имеет новую строку, встроенную в имя.
Для первой команды вывод будет:
$ find . \! -name '.' -type d -prune | grep -f ids.txt | xargs echo rm -rf
rm -rf _1effaj ./hello_1effaj
(он попытается удалить каталог с именем _1effaj
, но hello?_1effaj
будет не тронут)
$ find . \! -name '.' -type d -prune -print0 | grep -z -f ids.txt | xargs --null echo rm -rf
rm -rf ./hello
_1effaj ./hello_1effaj
Это успешно удалит каталог hello?_1effaj
.
Как мне проверить, есть ли у меня такое имя файла? :
find -name '*
*'
это должно работать в любой оболочке POSIX.
Или в bash вы можете использовать: find -name \*$'\n'\*