Вы должны добавить ; до того, как сделано, или поместите новую строку здесь.
for file in /dev/DataStage/myProject/source/TEST/MyFile_*.csv; do echo "Testing" ; done
На мой взгляд, ваше решение вполне подходит для этой задачи. Однако это медленно, потому что порождает 3 процесса на файл. Я считаю, что Awk здесь лучше подходит, потому что он позволит прочитать целую партию файлов (, как это разрешено ARG _MAX ), за один раз, используя {} +
вместо {} \;
.
GNU Awk:
find. -type f -exec gawk '
BEGINFILE{c1=c2=c3=0}
/AAA/ {c1=1}
/BBB/||/CCC/{c2=1}
/DDD/ {c3=1; nextfile}
ENDFILE{if(c1 && c2 && !c3)print FILENAME}
' {} +
POSIX*:
find. -type f -exec awk '
FNR==1{
if(NR>1 && c1 && c2 && !c3)print f
c1=c2=c3=0
f=FILENAME
}
/AAA/ {c1=1}
/BBB/||/CCC/{c2=1}
/DDD/ {c3=1; nextfile}
END{if(c1 && c2 && !c3)print f}
' {} +
*На самом деле, nextfile
все еще не POSIX, но он был принят к следующему выпуску стандарта . Вы можете удалить его для соответствия POSIX issue 7; результат будет тот же, но с потерей производительности.
Примечание.:Awk выручает, если у него нет прав на чтение файла. В GNU Find просто добавьте флаг -readable
, чтобы избежать этого. Если GNU Find недоступен, в качестве дополнительного фильтра можно использовать Test :
find. -type f -exec test -r {} \; -exec awk '
...
' {} +
Но запуск теста для каждого файла приводит к снижению производительности.
Дополнительная литература:
Вот альтернативный способ. Он работает, сначала создавая списки файлов, содержащих каждое отдельное слово :
.find. -type f -exec grep -lF 'AAA' {} + > files_with_AAA
find. -type f -exec grep -lF 'BBB' {} + > files_with_BBB
...
Затем условия могут быть реализованы путем обработки списков:
grep -Ff files_with_BBB files_with_AAA # AAA & BBB
grep -Fvf files_with_BBB files_with_AAA # AAA & ~BBB
sort -u files_with_AAA files_with_BBB # AAA | BBB
Если нужно оценить большое количество файлов и несколько выражений, это может быть быстрее, так как не нужно повторно сканировать каждый файл.
Мне было бы интересно увидеть сравнение времени с этими решениями, особенно для ripgrep , в котором реализована -параллельная обработка.
GNU grep
grep -rLZ 'DDD' | xargs -0 grep -lZ 'AAAA' | xargs -0 grep -lE 'BBB|CCCCC'
# if your search terms are literal strings
grep -rLZF 'DDD' | xargs -0 grep -lZF 'AAAA' | xargs -0 grep -lF -e 'BBB' -e 'CCCCC'
rg
. Обратите внимание, что рекурсивный поиск включен по умолчанию, а некоторые файлы также игнорируются по умолчанию. Вам нужно использовать -u
, если вы не хотите, чтобы файлы, подобные .gitignore
, влияли на результаты. Используйте -uu
для дополнительного поиска скрытых файлов. Используйте -uuu
, если вы хотите также искать двоичные файлы. rg --files-without-match -0 'DDD' | xargs -0 rg -l0 'AAAA' | xargs -0 rg -l 'BBB|CCCCC'
# if your search terms are literal strings
rg --files-without-match -0F 'DDD' | xargs -0 rg -l0F 'AAAA' | xargs -0 rg -lF -e 'BBB' -e 'CCCCC'
rg
многострочным соответствием rg -lUP '(?s)\A(?!.*DDD)(?=.*(BBB|CCCCC)).*AAAA'