Существует возможность grep -f MY_FILE
поиска шаблонов, взятых из файла, а не указанных непосредственно в командной строке.
Есть ли возможность сделать что-то подобное с find
командой и позволить ей считывать шаблоны для поиска из входного файла?
решение1
find
похоже, не имеет таких встроенных возможностей, но вы можете использовать его xargs
для создания нескольких find
команд с использованием аргументов из файла, например:
xargs -a patterns.txt -I% find Pictures/ -name %
где patterns.txt
будет список шаблонов, подходящих для -name
фильтра, по одному шаблону на строку. Обратите внимание, что там нет начальных/конечных пробелов, так как они будут включены в шаблон. Пример:
*.jpg
2018-06-*
*foo*
unicorn.png
Примечание:Хотя этот ответ выглядит довольно простым и элегантным, в комментариях справедливо отмечено, что у него есть несколько недостатков:
Производительность не слишком высока для больших папок или большого количества шаблонов, поскольку он будет запускаться
find
один раз для каждого шаблона в вашем файле, заставляя многократно сканировать всю папку поиска.Из-за этого, также если у вас есть несколько шаблонов, которые потенциально могут перекрываться (например,
*.jpg
и*foo*
), файлы, соответствующие более чем одному шаблону, будут появляться в результате столько же раз. Если вы в любом случае печатаете только имена, вы можете перенаправить вывод,sort -u
чтобы удалить дубликаты, но если вы, например, удалите эти результаты или выполните какие-либо-exec
команды для них, это может быть более нежелательным.Если какой-либо из этих недостатков является проблемой для вашего варианта использования, возможно, лучше выбрать один из альтернативных вариантов.
Пояснение к команде:
xargs
прочитает список аргументов и использует их для создания и запуска новой командной строки.-a patterns.txt
сообщает ему, что нужно читать из этого файла вместо стандартного ввода.-I%
говорит ему не просто добавлять прочитанные аргументы в конец командной строки, а заменить символ%
в командной строке, который вы указали, одним аргументом. Это подразумевает создание и выполнение одной отдельной команды для каждого входного аргумента.find Pictures/ -name %
— это командная строка, в которую мы хотим вставить аргументы, заменив%
. Здесь не нужно заключать в кавычки, посколькуxargs
позаботится о том, чтобы каждый вставляемый аргумент обрабатывался как отдельный токен и не разделялся сам по себе. Конечно, вы можете заменитьPictures/
свой собственный каталог поиска, а также использовать другой и/или больше фильтров, чем просто-name
. Поскольку мы используем опцию вставки, вы также можете добавлять действия, например,-exec ...
в конец команды.
решение2
Вы можете просто создать регулярное выражение из содержимого вашего файла, используя paste -sd'|' bar
.
find ~/foo -regextype egrep -regex "^.*/($(paste -sd'|' bar))$"
Регулярное выражение будет"^.*/(a|b)$"
решение3
Не так давно я сделалотвечатькоторый объединяет несколько шаблонов с помощью -regex
флага в find
. На основе этого мы можем создать небольшой скрипт или функцию для выполнения той же работы, но составить список шаблонов из файла.
#!/bin/bash
read_file(){
local full_pattern=""
while IFS= read -r pattern; do
if [ -z "$full_pattern" ];then
full_pattern="$pattern"
continue
fi
full_pattern="$full_pattern\|$pattern"
done < "$1"
echo "$full_pattern"
}
fp=$(read_file "$1" )
find "$2" -type f -regex ".*\($fp\).*$"
Что это делает:
- мы вызываем скрипт как
findf.sh input.txt /etc
, где первый позиционный параметр - это файл с шаблонами, а второй - каталог, в котором нужно искать. GNU find предполагает.
каталог, если аргумент каталога опущен, поэтому$2
не требуется. - Функция
read_file
считывает входной файл, который является первым позиционным параметром скрипта. Это создает шаблон для-regex
флага. - Этот шаблон возвращается обратно в «основной» блок скрипта и сохраняется в
fp
переменной, которая затем передается вfind
команду.