На этот вопрос уже есть ответ здесь:
Там - это возможность использовать grep -f MY_FILE
, чтобы разрешить поиск шаблонов, взятых из файла, вместо того, чтобы указывать их непосредственно в командной строке.
Есть ли возможность сделать что-то подобное с командой find
и позволить ей читать шаблоны для поиска из входного файла?
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 ...
в конец команды. Вы можете просто создать регулярное выражение из содержимого вашего файла, используя paste -sd'|' bar
.
find ~/foo -regextype egrep -regex "^.*/($(paste -sd'|' bar))$"
Регулярное выражение будет "^.*/(a|b)$"
Не так давно я сделал ответ , который объединяет несколько шаблонов с использованием флага -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 предполагает наличие каталога .
, если аргумент directory опущен, поэтому $2
не требуется. read_file
считывает входной файл, который является первым позиционным параметром, в сценарий. Это создает шаблон для флага -regex
. fp
, что передается в команду find
.