私はいくつかのディレクトリを持っていますが、その中には3つの深さがあり、混在したファイルタイプが含まれています。私がしなければならないのは、rm -rf
filetypeを含まないすべてのサブディレクトリです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を使用して実行できるかどうかはわかりませんが、find
justとを使用して実行できると思います。bash
find
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.1
file.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~''