Unix delete with find: удалить все файлы, перечисленные в файле

в моем корневом каталоге у меня есть пара папок с именем типа AA,BB,CC etc., каждый из которых содержит файлы в формате AA1001.txt,BB1002.txt etc.
В моей корневой папке, у меня также есть файл all_to_delete, который имеет кучу имен файлов, разделенных новыми строками, таким образом, выглядит примерно так:

AA1004.txt

BB3004.txt

BB3005.формат txt. ..

теперь я хочу пройти через все поддиректории в корне каталог и удалить все файлы, соответствующие заданному имени файла. До сих пор, я пробовал что-то вроде:

while read line; do find . -type f -name $line -exec rm -f {} ;; done
Хотя, это не может работать как уже while read line; do find . -type f -name $line; done не соответствует файлам (как найти дает выход как ./AA/AA1001.txt ...)

у вас есть решение для меня?

12
задан djsmiley2k
03.03.2023 18:06 Количество просмотров материала 3698
Распечатать страницу

3 ответа

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

вместо этого я бы сделал что-то вроде этого:

find . -type f -name "*txt" | grep -wFf to_delete.txt | xargs -I{} rm '{}'

фокус в том, чтобы дать grep файл как список моделей поиск (-f). The -F убедитесь, что ваши имена файлов рассматриваются как строки, а не регулярные выражения, таким образом, ваши имена файлов ca содержат специальные символы, такие как * или [ или |. Затем вы переходите к xargs и использовать процитировано '{}', иначе он не на пробел, чтобы удалить файлы.

Примечание: предполагается, что все имена файлов уникальны, одно имя не может содержаться в другом. Например, что у вас нет файлов с именем foo и foobar. Если да, то по шаблону foo, это удалит оба файла. Чтобы избежать этого, используйте:

while IFS= read -r line; do find . -name "$line" -delete; done < to_delete.txt 

С man find:

   -delete
          Delete files; true if removal succeeded. 
1
отвечен terdon 2023-03-05 01:54

насколько буквально Вы описываете свою проблему?  Имена каталогов состоят из двух символов?  Будет файл BB3004.txt всегда находиться в каталоге BB?  Если да, то вам не нужно find; просто извлечь имя каталога из первых двух символов имени файла:

while read -r line
do
    dir=$(expr "$line" : '\(..\)')
    echo rm "$dir/$line"
    rm "$dir/$line"
done < all_to_delete
1
отвечен Scott 2023-03-05 04:11

есть много разных способов сделать это, но вот как я это сделаю:

создал тестовый каталог с несколькими файлами:

% ls ./teste
lala  lele  lolo  lulu

создал файл со списком тех, кого я хотел бы удалить:

% cat to_delete.txt 
lele
lolo
lulu

здесь я петлю корыта каждую строку ' to_delete.txt ' файл, передавая имя файла команде find, а затем, наконец, удалить их:

% while read filename; do find ./teste -name ${filename} -print0 | xargs -0 rm -vf; done < to_delete.txt 
removed `./teste/lele'
removed `./teste/lolo'
removed `./teste/lulu'

сделано:

% ls ./teste                                                                                      
lala
1
отвечен Luis Nardella 2023-03-05 06:28

Постоянная ссылка на данную страницу: [ Скопировать ссылку | Сгенерировать QR-код ]

Ваш ответ

Опубликуйте как Гость или авторизуйтесь

Имя
Вверх