プログラミング

bash findの正規表現で否定先読み(not)を入れたかったけどエラる

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単体でやることもないでしょう。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です