Передача нескольких каталогов в параметр -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

  • Использование find для поиска каталога и удаления его подкаталогов
  • Самый дешевый способ найти самый старый файл (рекурсивно) из каталога с большой нагрузкой
  • Как я могу выполнить поиск по ширине с помощью `find`?
  • Значение @ 0 в сценарии оболочки
  • Что означает, что точка скроет косую черту с косой чертой (.//)?
  • Установка разрешений на основе прав пользователя
  • Как найти все репозитории git в заданных папках (быстро)
  • Почему `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

    Отключение питания USB-порта. Или отключите питание всей подсистемы USB

    Как выйти из системы, когда рабочий стол замерзает?

    Миграция из archlinux в gentoo

    Как переключаться между пользователями на одном терминале?

    Команда для отображения всех изображений в каталоге в одном окне браузера, от термина?

    Настройка владельца и группы для установки OpenCart на CentOS 6.3

    Объединение двух файлов с уникальным идентификатором

    nohup: игнорирование ввода и перенаправление stderr в stdout

    Как изменить переменную, которая является частью значения другой переменной

    Правильный способ добавления пользователей в репозиторий Subversion

    Возможно ли изменить сообщение об ошибке, вызванное расширением параметра, используя формат «$ {pattern:? Word}»?

    Как я могу заставить свою Linux-систему широковещать свой IP-адрес динамически?

    dbus: Не удалось активировать услугу «org.freedesktop.login1»: тайм-аут

    Где теперь Lenny ISO, что Squeeze отсутствует?

    Как исправить вход в графический режим на Fedora 25

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