bashを使用しているので、sed、awk、findなどの外部ツールなしでこれを行うことができます。
#!/bin/bash
shopt -s globstar
for filename in **/*a*a*; do
[[ "$filename" =~ u ]] || echo "$filename"
done
これが絶対に厄介である必要がある場合、私は使用します:
awk '/a.*a/ && ! /u/' data
アップデート:
gniourf_gniourfの丁寧な警告に従って、正規表現の代わりにパス名展開(globs)を使用するとパフォーマンスが向上する場合があります。これが(非科学的な)ベンチマークです:
$ rm -f file
$ for (( i=1000000; i-- ; )); do echo u >> file; done
$ time bash -c 'while read i; do [[ $i = *u* ]]; done < file'
real 0m8.291s
user 0m6.570s
sys 0m1.717s
$ time bash -c 'while read i; do [[ $i =~ u ]]; done < file'
real 0m10.416s
user 0m8.676s
sys 0m1.735s
「ユーザー」行は、私たちが関心を持っている行です。
これにより、fileglobが正規表現よりも約30%速く実行されているように見え、100万件のレコードをテストして肯定的な結果が得られます。
奇妙なことに、テストが失敗してもそれほど改善はありません。
$ time bash -c 'while read i; do [[ $i = *a* ]]; done < file'
real 0m8.244s
user 0m6.601s
sys 0m1.639s
$ time bash -c 'while read i; do [[ $i =~ a ]]; done < file'
real 0m9.757s
user 0m8.121s
sys 0m1.630s
これは、これらの100万回のテストで23%の速度向上にすぎません。この種のシェルスクリプトの最適化が重要な場合(何百万ものテストを実行していて、CPUサイクルに余裕があるとは思わないため)、コースがawkからbashに移行するときに、gniourf_gniourfの提案を検討してください。