役に立たないファイル(たとえば、、、、、など)を含むいくつかのディレクトリがあります*.tmp
。desktop.ini
Thumbs.db
.picasa.ini
すべてのドライブを検索して一部のファイルのみを含むディレクトリを見つけるにはどうすればよいですか?
答え1
、および/または以外の名前がない*.tmp
すべてのdesktop.ini
ディレクトリThumbs.db
を見つけるには、次の手順を実行します.picasa.ini
。
find . -type d -exec bash -O dotglob -c '
for dirpath do
ok=true
seen_files=false
set -- "$dirpath"/*
for name do
[ -d "$name" ] && continue # skip dirs
seen_files=true
case "${name##*/}" in
*.tmp|desktop.ini|Thumbs.db|.picasa.ini) ;; # do nothing
*) ok=false; break
esac
done
"$seen_files" && "$ok" && printf "%s\n" "$dirpath"
done' bash {} +
find
これは、現在のディレクトリの下(含まれている)のディレクトリを見つけてシェルスクリプトに渡すために使用されます。
シェルスクリプトは指定されたディレクトリパスを繰り返し、各ディレクトリパスに対して*
その中で展開されます(隠し名前をキャプチャするようにdotglob
シェルオプションを設定します)。bash
次に、結果の名前のリストを繰り返して、検索したい特定のパターンと名前と一致させます(ディレクトリを無視)。もし見つけたらその他名前がリストと一致しない場合(from has was)ok
に設定され、内部ループから外れます。false
true
次のタイプを除くすべてのタイプのファイルを見ると、このseen_files
変数は次のようになります。true
目次(またはディレクトリへのシンボリックリンク)。この変数は、他のサブディレクトリのみを含むサブディレクトリを報告するのを防ぐのに役立ちます。
$seen_files
次に、and $ok
(true
または)を実行してfalse
両方の場合、true
そのディレクトリに少なくとも1つの一般的なファイルが含まれていることを意味します。リスト内のファイル名のみを含める、ディレクトリのパス名を印刷します。
変える
set -- "$dirpath"/*
for name do
あなたは明らかにこれを行うことができます
for name in "$dirpath"/*; do
代わりに。
テスト:
$ tree
.
`-- dir
|-- Thumbs.db
`-- dir
|-- file.tmp
`-- something
2 directories, 3 files
(find
ここでコマンドが実行され、出力が生成されます...)
./dir
つまり、ディレクトリ./dir
にはリストの名前(ディレクトリを無視)だけが含まれ、./dir/dir
他のコンテンツも含まれます。
[ -d "$name" ] && continue
コードから削除すると、リスト()にない名前が./dir
含まれているため、ディレクトリが見つかりません。dir
答え2
find、xargs、ls、sed、wc、および awk コマンドの組み合わせを使用すると機能します。
find . -type f \( -iname "desktop.ini" -o -name "thumb.db" \) -printf %h\\0 | xargs -0 -I "{}" sh -c 'printf "{}\t"; ls -l "{}" | sed -n "1!p" | wc -l' | awk '$2 == "1" {print $0}'
説明する:
find .
現在のディレクトリで検索-type f
ファイルのみ検索\( -iname "desktop.ini" -o -name "thumb.db" \)
ここで、ファイル名は「desktop.ini」または「thumb.db」で、大文字と小文字を区別しません。printf %h\\0
ファイル名+ASCII NULの先頭ディレクトリを印刷します。xargs -0 -I "{}" sh -c 'printf "{}\t"; ls -l "{}"
出力ディレクトリを印刷し、ls -l
各ディレクトリで実行sed -n "1!p" | wc -l'
ファイル全体とディレクトリを含む最初の行を除き、行数を計算しますls -l
。awk '$2 == "1" {print $0}'
数が「1」に等しい場合は、その行を印刷します。
答え3
ファイルまたはフォルダを名前で指定することをお勧めします。たとえば、次のようになります。
find ${HOME} -type f -iname thumbs.db -print0 | xargs -0 --no-run-if-empty rm
() "thumbs.db"-type f
という名前のすべてのファイルを見つけて()削除します()。-iname
i
iname
rm
次のファイル名パターンを使用できます。
find ${HOME} -type f -iname '*.tmp' -print0 | xargs -0 --no-run-if-empty rm
警告する:ご入力いただいた内容にご注意ください。リクエストなしで削除できます。
定期的にバックアップしてください。クリーンアッププロセスを開始する前に良い時間になることができます!
何を期待するかを知りたい場合は、rm
作業を実行する前にファイルのリストを見てください。たとえば、次のようになります。
find ${HOME} -type f -iname thumbs.db -print0 | xargs -0 --no-run-if-empty ls -l
答え4
GNUfind
とGNUを使用すると、すべてのファイルを報告して一致させるawk
ことができます。find
awk
find . -depth -type d -printf '%p/\0' -o -printf '%p\0' |
gawk -F/ -v OFS=/ -v RS='\0' -v IGNORECASE=1 '
/\/$/ {
NF--
if (good[$0] == 0 && bad[$0] > 0) print
next
}
{
name = $NF
NF--
if (name ~ /^(.*\.tmp|desktop\.ini|Thumbs\.db|\.picasa\.ini)$/)
bad[$0]++
else
good[$0]++
}'
空のディレクトリを含めるには、削除してください&& bad[$0] > 0
。大文字と小文字を区別するには、削除してください-v IGNORECASE=1
。