特定のファイル形式fooを含むディレクトリを検索するには、「検索」を使用してください。

特定のファイル形式fooを含むディレクトリを検索するには、「検索」を使用してください。

私はいくつかのディレクトリを持っていますが、その中には3つの深さがあり、混在したファイルタイプが含まれています。私がしなければならないのは、rm -rffiletypeを含まないすべてのサブディレクトリですfoo

これはfind何とか達成できますか?私は次のようにfindを使用できることを知っています。

find . ! -name '*.foo' -delete

どの種類のファイルも含まれていないディレクトリ内のすべてのファイルを削除します*.foo。これで、不要なファイルだけでなく、含まれていないすべてのディレクトリとサブディレクトリも削除するにはどうすればよいですか*.foo

答え1

(あなたの質問は不明です。ディレクトリにおよびsome.fooが含まれている場合はsome.bar削除する必要がありますか?私はこれをそのようなディレクトリを保存する必要があるという意味に解釈しました。)

ファイル名に改行文字が含まれておらず、ディレクトリが一致しない場合は、次の*.fooスクリプトが機能します。原則は、ディレクトリが葉から上に移動さ-depthれ、ファイル*.fooが見つかると、インクルードディレクトリとすべての親ディレクトリが表示されることですprotected。到着した保護されていないファイルは*.foo削除されるディレクトリです。トラバースの順序により、-depthディレクトリは常に*.foo保護できるファイルの後に到達します。警告:最小限のテストのみを行うと、削除による責任はechoあなたにあります。

find . -depth -name '*.foo' -o -type d | awk '{
    if ($0 ~ /\.foo$/) {
        while (sub("/+[^/]+$", "")) {protect[$0]=1;}
    } else {
        if (!protect[$0]) {
            gsub("[\\\001-/]", "\\\\&"); # protect file names for xargs
            print;
        }
    }
}' | xargs echo rm -rf

今回はzshソリューションを提案しません。

答え2

これがjustを使用して実行できるかどうかはわかりませんが、findjustとを使用して実行できると思います。bashfind

tree_contains_foo_files()
{
    # return true (0) as soon as we find a "*.foo" file
    find "$1" -type f -name "*.foo" -print0 |
        read -r -d $'\0' file && return 0

    return 1
}

find . -depth -type d -print0 |
while read -r -d $'\0' dir; do
    if ! tree_contains_foo_files "$dir"; then
        rm -rf "$dir"
    fi
done

このテストツリーが与えられたら:

.
./dir1
./dir1/dir1.1
./dir1/dir1.1/dir1.1.1
./dir1/dir1.1/dir1.1.1/file.foo
./dir1/dir1.1/file.bar
./dir2
./dir2/dir2.1
./dir2/file.bar
./dir3

私は次のような結果を得ます。

rm -rf ./dir2/dir2.1
rm -rf ./dir2
rm -rf ./dir3

私はこれがあなたが望むものだと思います。つまり、インクルードdir1のため削除しないでください。dir1/dir1.1/dir1.1.1file.foo

ただし、ディレクトリを複数回処理するため、大きなツリーの場合は速度が遅くなる可能性があります。効率が重要な場合は、より強力なプログラミング言語を使用します。

答え3

IIUYC、まず、次のコマンドを使用して不要なファイルをすべて削除できます

find . ! -type f -name '*.foo' -delete

これにより、一部のディレクトリが消去される可能性があります。その後、空のディレクトリ(および空のディレクトリのみを含むディレクトリなど)を削除できます。私の質問

find . -depth -mindepth 1 -empty -type d -exec rmdir -p -- {} +

答え4

許可されていない場合、findより簡単な解決策は次のとおりです。

find -type d -not -path . | while IFS='' read -r path; do [[ ! -e "$path/$notThisFile" ]] && echo "$path"; done

-e必要なテストに交換してください。

を含まないすべての内容を印刷する必要があります$notThisFile


ファイルを含む非表示になっていないすべてのサブディレクトリが強調表示される詳細な例:

find -type d -not -path . | while IFS='' read -r path; do
  [[ ! -e "$path/$notThisFile" ]] && echo "$path"
done | sed -r 's~^([^.]*)/'"$notThisFile"'$~\033[1;37m\1\033[0m~''

関連情報