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

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

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

 #! /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

  • rsync только файлы новее, чем заданная дата, с --delete
  • Найти все файлы, которые были в последний раз изменены в определенный день - например, в понедельник?
  • Найти файлы рекурсивно, которые старше одного года и не принадлежат конкретному пользователю
  • Почему команда GNU find -execdir ведет себя иначе, чем поиск BSD?
  • Входной сигнал трубы для поиска команды
  • Рекурсивно найти файлы, которые имеют процент общих линий
  • Простой сценарий bash для резервного копирования и удаления каталогов
  • Параллелизировать рекурсивное удаление с помощью find
  • 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 {} \; 
    Interesting Posts

    Существует ли дистрибутив Linux, который работает на процессоре AllWinner A10S?

    управление питанием жестких дисков с USB-накопителем

    Системный заказ загрузки не найден (безопасная загрузка не включена)

    Хотя цикл для целых чисел с пользовательским вводом

    Как удалить упрямый каталог?

    rsnapshot удаленный сервер – лучшая практика для разрешений

    Получение новой версии GEOS, чем то, что доступно в репозиториях Debian

    Связать аппаратное обеспечение с конкретным / dev / input / event *

    «Неожиданный конец файла», возвращенный из скрипта BASH

    Установка конфликтов Postfix с пакетом MySQL-server

    Linux Последняя команда weird output? Мусор для IP-адреса

    Групповая подстановка Sed добавляется в OSX, а не в ожидаемый sub в Linux

    Fedora 23 больше не загружается (GRUB: поддерживается минимальное редактирование строк в формате BASH).

    Как запустить демон с настраиваемыми параметрами

    Как я могу показать баннер SSH перед сообщением «login as:»?

    Linux и Unix - лучшая ОС в мире.