bash findの正規表現で否定先読み(not)を入れたかったけどエラる、というお話になります。
findでは正規表現が使えますが、not、(?!)
構文を使うとエラーになってしまいます。んー、わからん。
find -L -regextype posix-extended -regex '(?!.*Andrea Bocelli)\.(wav|mp3|flac|wave|mp4|avi)'
find -L -regextype posix-extended -regex '(?!.*Andrea Bocelli)(?=.*)\.(wav|mp3|flac|wave|mp4|avi)'
find -L -regextype posix-extended -regex '(?!.*Andrea Bocelli)*\.(wav|mp3|flac|wave|mp4|avi)'
find -L -regextype posix-extended -regex '((?!.*Andrea Bocelli).)*\.(wav|mp3|flac|wave|mp4|avi)'
find -L -regextype posix-extended -regex '(?!.*Andrea Bocelli).*\.(wav|mp3|flac|wave|mp4|avi)'
なので仕方ないので、正規表現ではないですが、-not
でBash Extended Globbingで指定してやるのが良さそうです。
find -L -regextype posix-extended -regex '.*\.(wav|mp3|flac|wave|mp4|avi)'
find -L -regextype posix-extended -regex '.*\.(wav|mp3|flac|wave|mp4|avi)' -not -name '*Andrea Bocelli*'
bash globはあまり知られてないですが、割と正規表現に近いこともできます。
Bash Extended Globbing | Linux Journal
あー、
find -L -regextype posix-extended -regex '.*\.(wav|mp3|flac|wave|mp4|avi)' -not -name '*+(Andrea Bocelli|_current)*'
できなかった。忘れてください。
頑張って方法を考えました。agとかが良さげかと思ったけどだめ。やっぱawkですね。
awkで否定をするのも少しまた一苦労したのですが。
AWK negative regular expression – Unix & Linux Stack Exchange
以前awkのドキュメント読んだときにちらっと見た気がするでもないんだけど覚えてなかった。
find -L -regextype posix-extended -regex '.*\.(wav|mp3|flac|wave|mp4|avi)' | awk '!/Andrea Bocelli|_current/'
これでいけます。
-not -name
はファイル名、awk
はディレクトリ名を含めた行全体に適用されるので、そこらへん使い分けたら良いと思います。
-prune
でディレクトリを指定できるとあったがよくわからない。まぁ、できないことは他のツールや言語で補えば良いと思います。無理にfind
単体でやることもないでしょう。