Передача нескольких каталогов в параметр -prune в поиске

Я использую find для поиска и удаления файлов резервных копий, но хочу исключить определенные каталоги из поиска. Резервные имена файлов могут заканчиваться в .bck , bak , ~ или backup .

Код минимального рабочего примера (MWE) с тремя исключаемыми директориями:

  • Как исключить файлы / каталоги из find с помощью аргумента программы в bash?
  • Как использовать команду pipe для открытия каталога после поиска?
  • Исключить все подкаталоги, кроме одного определенного пути в команде find
  • Как найти общий размер файла, сгруппированный по расширению
  • Список владельцев файлов
  • Как использовать cloc для поиска строк кода в пакете debian
  •  #! /bin/bash find . -type d \( -path "./.*" -o -path "./Music" -o -path "./Documents" \) -prune -o -type f \( -name "*.bck" -o -name "*.bak" -o -name "*~" -o -name "*.backup" \) -print0 | xargs -0 --no-run-if-empty trash-put 

    Синтаксис \( -path "dir1" -o -path "dir2" ... -o -path "dirN" \) -prune кажется немного неуклюжим, особенно если есть около десяти каталогов, чтобы исключить, хотя я показал только три в MWE.

    Есть ли более элегантный способ использования либо входного файла, со списком исключенных каталогов, либо конструкции с массивом или списком, которые могут быть нажаты в эксплуатацию?

    Мне жаль, что я не был более явным, когда писал свой первоначальный вопрос.

    NB: trash-put – это утилита, которая перемещает файлы в Trashcan а не удаляет их [1].

    [1]. https://github.com/andreafrancia/trash-cli

  • Объединение опций в команду find
  • Поиск файлов, имеющих подтвержденный дубликат в том же каталоге, рекурсивно
  • Распределение порядка стека каталога в zsh
  • Повторение аргумента командной строки
  • найти файл и усечь его
  • Как получить абсолютный путь от использования команды find unix
  • 4 Solutions collect form web for “Передача нескольких каталогов в параметр -prune в поиске”

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

     $ tree -a . ├── a ├── .aa ├── .aa.bak ├── a.bck ├── b ├── .dir1 │  └── bb1.bak ├── dir2 │ └── bb2.bak ├── b.bak ├── c ├── c~ ├── Documents │  └── Documents.bak ├── exclude.txt ├── foo.backup └── Music └── Music.bak 

    Если я правильно понял пример, который вы разместили правильно, вы хотите переместить a.bck , .aa.bak , b.bak , c~ , foo.backup и dir2/bb2.bak в корзину и оставить .aa.bak , .dir1/bb1.bak , Documents/Documents.bak и Music/Music.bak где они есть. Поэтому я создал файл exclude.txt со следующим содержимым (вы можете добавить столько, сколько хотите):

     $ cat exclude.txt ./.*/ ./Music ./Documents 

    Я использую ./.*/ потому что я понял, что ваша оригинальная находка означает, что вы хотите переместить скрытые файлы резервных копий ( .foo ), которые находятся в текущем каталоге, но исключают любые файлы резервных копий, которые находятся в скрытых каталогах ( .foo/bar ). Итак, теперь я могу запустить команду find и использовать grep для исключения нежелательных файлов:

     $ find . -type f | grep -vZf exclude.txt | xargs -0 --no-run-if-empty trash-put 

    Параметры Grep:

      -v, --invert-match Invert the sense of matching, to select non-matching lines. (-v is specified by POSIX.) -f FILE, --file=FILE Obtain patterns from FILE, one per line. The empty file contains zero patterns, and therefore matches nothing. (-f is specified by POSIX.) -Z, --null Output a zero byte (the ASCII NUL character) instead of the character that normally follows a file name. For example, grep -lZ outputs a zero byte after each file name instead of the usual newline. This option makes the output unambiguous, even in the presence of file names containing unusual characters like newlines. This option can be used with commands like find -print0, perl -0, sort -z, and xargs -0 to process arbitrary file names, even those that contain newline characters. 

    С помощью GNU find (т. Е. В не встроенных Linux или Cygwin) вы можете использовать -regex для объединения всех этих -path символов в одно регулярное выражение.

     find . -regextype posix-extended \ -type d -regex '\./(\..*|Music|Documents)' -prune -o \ -type f -regex '.*(\.(bck|bak|backup)|~)' -print0 | xargs -0 --no-run-if-empty trash-put 

    С FreeBSD или OSX используйте -E вместо -regextype posix-extended .

    Это скорее вопрос оболочки, чем вопрос find . С файлом, содержащим ( -name dir1 -o -name dir2 ) -prune (no "\"!), Вы можете просто сделать это:

     find ... $(< /path/to/file) 

    Не меняя сам вызов на поиск (для определения eval find или изменения IFS), это работает только с путями без пробелов.

    Если вы хотите, чтобы файл был проще, вы можете написать скрипт.

     # file content dir1 dir2 dir3 # script content #!/bin/bash file=/path/to/file # file may be checked for whitespace here grep '[^[:space:]]' "$file" | { empty=yes while read dir; do if [ yes = "$empty" ]; then echo -n "( " empty=no else echo -n " -o " fi echo -n "-name ${dir}" done if [ no = "$empty" ]; then echo -n " ) -prune" fi; } 

    И использовать

     find ... $(/path/to/script) 

    вместо.

    Group -path ... -prune в одно выражение, заключенное в \( ... \) с использованием логики -o ( или ).

     find /somepath \( -path /a -prune -o \ -path /b -prune -o \ -path /c -prune \ \) \ -o -print 

    В примере не будут итерации каталогов или файлов в /somepath/a , /somepath/b и /somepath/c .

    Вот более конкретный пример, использующий несколько действий.

     find / \( -path /dev -prune -o \ -path /proc -prune -o \ -path /sys -prune \ \) \ -o -printf '%p ' -exec cksum {} \; 
    Linux и Unix - лучшая ОС в мире.