Twitterでそういった処理について見かけたので、念のため備忘として残しておく事にする。 findコマンドではnotで指定条件以外を出力できるのだが、対象ディレクトリ配下に指定したファイル名以外のものが入っているとヒットしてしまうのでそれでは対応できない。

なので、一度その指定したファイル名のあるディレクトリのみを取得し、その後findで得た全体のディレクトリ名を突合させてやるという方法で抽出ができる。

find ./ -type d | grep -v -f <(find ./ -type f -name "*filename" -printf "%h\n")
find ./ -type d | grep -v -f <(ls -1 ./*/?(filename)|dirname $(cat)) # exglobを有効にしている場合

[root@BS-PUB-CENT7-01 test_dir]# find ./
./
./test001
./test001/test.log
./test002
./test002/test.log
./test003
./test003/test.log
./test004
./test004/test.log
./test005
./test006
./test006/test.log
./test007
./test007/test.log
./test008
./test008/test.log
./test009
./test009/test.log
./test010
./test010/test.log
./test011
./test011/test.log
./test012
./test012/test.log
./test013
./test013/test.log
./test014
./test014/test.log
./test015
./test015/test.log
./test016
./test016/test.log
./test016/test.txt
./test017
./test017/test.log
./test018
./test018/test.log
./test019
./test019/test.log
./test020
./test020/test.log
[root@BS-PUB-CENT7-01 test_dir]# find ./ -type d | grep -v -f <(find ./ -type f -name "*.log" -printf "%h\n")
./
./test005
[root@BS-PUB-CENT7-01 test_dir]# find ./ -type d | grep -v -f <(ls -1 ./*/?(*.log)|dirname $(cat))
./
./test005