Zsh

刪除除 1 之外的所有重複圖像文件

  • December 12, 2021

我有一個包含很多重複項的圖像文件夾,我想刪除除一個之外的所有重複項。

Google搜尋後,我從這篇文章中發現了這個聰明的腳本,它簡潔地完成我想要它做的事情:

#!/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 shell 腳本時,我仍然相當陌生,所以我不確定每個部分的實際命令/標誌在這裡做什麼,所以我無法根據我的特定需求對其進行修改。

據我了解:

find "${1:-.}" -type f ! -empty -print0- 在目前目錄中搜尋非空文件並列印文件名。(雖然不知道這件作品是什麼"${1:-.}"意思)

| xargs -0 md5 -r- 將上面的結果(通過xargs -0命令?)通過管道傳遞到md5命令中以獲取每個文件的 md5 雜湊簽名(-r反轉輸出以使其成為單行?)

awk '$1 in a{sub("^.{33}","");printf "%s\0",$0}a[$1]+=1{}'- 這就是我迷路的地方..

  • $1 in a{sub("^.{33}","")- 將輸入直到第一個空白字元,並將字元串開頭的前 33 個字元替換為空 ( sub("^.{33}","")
  • printf "%s\0"- 格式列印整個字元串
  • a{...,$0}- 我不確定這是做什麼的
  • a[$1]+=1{}- 也不確定

xargs -0 rm -v --- 將結果傳遞給rm命令,通過 列印每個文件名-v,但我不確定語法--的用途。

當我執行它時,它會像這樣輸出,./test3.jpg./test2.jpg./test.jpg: No such file or directory所以一定存在格式問題。

我的問題是:

  1. 可以修改它以刪除除 1 之外的所有文件嗎?
  2. 有人可以幫助解釋我上面概述的命令/語法含義的差距嗎?

我確信這對於熟悉 UNIX 的人來說可能很容易,但不幸的是,那個人不是我。先感謝您!

對於上下文:我在 macOS BigSur 11 的 ZSH 中執行它。

我將重點關注awk-part 這裡:

md5 -r返回 32 個字元的 md5-sum,然後是文件名。因此,md5-sum 是awk.

$1 in a{...}

表示“如果$1(此處:md5-sum)在數組中作為索引找到,a則執行命令 {…}”。所以a將用作一個數組,其中 md5 和作為已經看到的索引。請注意,如果此值不存在或為 0,則不會執行命令 - 因此第一次看到 md5-sum 時,不會返回文件名。如果它是任何其他值(包括字元串),則條件為真,並執行命令。

sub("^.{33}","");printf "%s\0",$0

將從開頭刪除 33 個字元,即 md5-sum 和後面的空格,然後在末尾使用 NUL 分隔符列印其餘的(原始文件名)。NUL 分隔對於帶有空格的文件很重要。見或中。-print0_ 請注意,如果 md5-sum 已經在 array 中,則僅執行此命令,因此不返回第一個匹配項(即僅顯示重複項,然後將其刪除)。man find``-0``man xargs``a

a[$1]+=1{}

“將 1 添加到數組的元素 $1 a”,$1 是 md5-sum。a因此,一旦看到 md5-sum ,就會設置此值。它是重複計數器。’{}’ 是空命令。這是必要的,因為awk如果滿足條件並且沒有給出命令,預設情況下會返回完整記錄。


警告

據我所見,該腳本適用於帶有空格的文件,但我認為對於名稱中帶有換行符的文件,它會失敗,因為awk沒有將 NUL 設置為記錄分隔符,然後預設為換行符。首先使用BEGIN {RS="\x0"}inawk設置它。

引用自:https://unix.stackexchange.com/questions/681186