次の内容を含む大きなファイルのリストが提供されます。
FILE1.doc
FILE1.pdf
FILE2.doc
FILE3.doc
FILE3.pdf
FILE4.doc
リストから名前が重複していないすべてのファイルを削除できるターミナルコマンドはありますか?この場合... FILE2.docとFILE4.doc?
答え1
Bashを使用すると、同じ名前を持つが拡張子が異なるファイルを持たないすべてのファイルが削除されます。
for f in *; do same=("${f%.*}".*); [ "${#same[@]}" -eq 1 ] && rm "$f"; done
この方法は、名前にスペースが含まれていても、すべてのファイル名に対して安全です。
どのように動作しますか?
for f in *; do
これにより、現在のディレクトリ内のすべてのファイルのループが開始されます。
same=("${f%.*}".*)
これにより、同じ基本名を持つすべてのファイルの名前を含むbash配列が作成されます。
$f
私たちのファイルの名前です。${f%.*}
拡張子のないファイル名。たとえば、ファイルがある場合、FILE1.doc
ファイル${f%.*}
はですFILE1
。"${f%.*}".*
デフォルト名は同じですが、拡張子はすべてファイルです。("${f%.*}".*)
この名前の bash 配列です。same=("${f%.*}".*)
変数に配列を割り当てますsame
。[ "${#same[@]}" -eq 1 ] && rm "$f"
そのベース名を持つファイルが1つしかない場合は削除します。
"${#same[@]}"
配列内のファイル数same
。[ "${#same[@]}" -eq 1 ]
そのファイルが1つしかない場合はtrue。&&
論理ANDです。rm "$f"
前の文が論理真を返す場合にのみ、次の文を実行します。done
これはサイクルの終わりを示します
for
。
答え2
ファイルのリストが任意のファイルにあると仮定する/tmp/files.list
と、次のようになりますls * > /tmp/files.list
。
これにより、sort -u /tmp/files.list
重複していない並べ替えられたファイルのリストが表示されます(上記の操作を実行した場合は必要ありません ls * > /tmp/files.list
)。あなたはいくつかでそれを処理することができますawk
スクリプトは以下からインスピレーションを得ました。これ、例えば
sort -u /tmp/files.list | awk '{
function basename(file) {
sub(".*/", "", file)
return file
}
curfil=$0;
if (basename(curfil)==basename(prevfil)) system("rm " + curfil);
prevfil=curfil;
}'
まだテストしたことはありませんので参考にしてください。
答え3
一見単純なように見えますが、複雑な別のアプローチは次のとおりです。
for x in `for i in *; do echo $i ; done | cut -d'.' -f1 | uniq -u `; do rm $x.*; done