かなり多くの重複を含むイメージフォルダがありますが、1つを除いてすべて削除したいと思います。
インターネット検索でこの賢いスクリプトを見つけました。この投稿簡単に言えばほぼ私が欲しいもの:
#!/bin/sh -eu
find "${1:-.}" -type f ! -empty -print0 | xargs -0 md5 -r | \
awk '$1 in a{sub("^.{33}","");printf "%s\0",$0}a[$1]+=1{}' | \
xargs -0 rm -v --
残念ながら、私はUNIXシェルスクリプトに初めて触れたので、各セクションの実際のコマンド/フラグがここで何をしているのかわからないので、特定の要件に合わせて変更することはできません。
私が理解している制限では:
find "${1:-.}" -type f ! -empty -print0
- 現在のディレクトリから空でないファイルを検索し、ファイル名を印刷します。 (この曲はどういう"${1:-.}"
意味かわかりません。)
| xargs -0 md5 -r
- 上記の結果(xargs -0
コマンドを介して?)をmd5
コマンドにパイプして各ファイルのmd5ハッシュ署名を取得します(-r
出力を反転して1行にしますか?)
awk '$1 in a{sub("^.{33}","");printf "%s\0",$0}a[$1]+=1{}'
- ここで迷子になりました..
$1 in a{sub("^.{33}","")
- 入力を最初の空白文字まで取得し、文字列の先頭の最初の33文字をnull(sub("^.{33}",""
)に置き換えます。printf "%s\0"
-Format は文字列全体を印刷します。a{...,$0}
- これが何であるかわからない。a[$1]+=1{}
- まだわからない
xargs -0 rm -v --
-各ファイル名を印刷して結果をrm
コマンドにパイプしますが、構文が何であるか-v
わかりません。--
実行してみると以下のように出力されるのに./test3.jpg./test2.jpg./test.jpg: No such file or directory
フォーマット問題があるようです。
私の質問は次のとおりです
- 1つを除くすべてのファイルを削除するように変更できますか?
- 上記のコマンド/構文の意味の違いを説明するのに役立つ人はいますか?
UNIXに慣れている人なら、これは簡単だと確信しています。しかし、残念ながら、その人は私ではありません。よろしくお願いします!
文脈:私はこれをmacOS BigSur 11のZSHで実行しています。
答え1
awk
ここでは - 部分に焦点を当てます。
md5 -r
32文字のmd5-sumとファイル名を返します。したがって、md5-sumはawk
。
$1 in a{...}
「$1
(ここで:md5-sum)が配列のインデックスとして見つかったら、a
{...}コマンドを実行してください」を意味します。したがって、a
md5を持つ配列とすでに表示されているインデックスとして使用されます。値が存在しないかゼロの場合、コマンドは実行されません。したがって、md5-sum を初めて表示するときのファイル名は次のようになります。いいえ後ろに。他の値(文字列を含む)の場合、条件はtrueでコマンドが実行されます。
sub("^.{33}","");printf "%s\0",$0
md5-sumと次の空白の33文字が最初から削除され、残り(元のファイル名)は最後にNUL区切り文字で印刷されます。スペースなどのファイルにはNUL区切りが重要です。またはを-print0
参照してください。このコマンドは、md5-sumがすでに配列にある場合にのみ実行されるため、最初の一致は返されません(つまり、重複した項目のみが表示され、後で削除されます)。man find
-0
man xargs
a
a[$1]+=1{}
「配列要素 $1 + 1 a
」、$1 は md5-sum です。したがって、a
md5-sum が表示されると値が設定されます。これは反復カウンタです。 「{}」は空のコマンドです。これはawk
、デフォルトで条件が満たされ、コマンドが指定されていない場合はレコード全体が返されるために必要です。
警告する
私が知っている限り、スクリプトは空白のあるファイルではうまく機能しますが、awk
NULはレコード区切り文字に設定されず、デフォルトはnewlinesに設定されているため、名前に改行文字を持つファイルでは失敗すると思います。BEGIN {RS="\x0"}
まず、inを使ってawk
設定してください。