Awk
避免在 awk 腳本中使用 ls 的空格和撇號問題
我在兩個(本地)設備中有許多相同的文件,碰巧我只在一個設備(A)中重命名了一些文件。我找到了以下方法來根據設備 A 中的新名稱重命名另一個設備 (B) 中的相同文件,這樣最後我的文件和名稱文件都相同,無需刪除或複制任何內容,而只是重命名。
事實上,我從 Hai Vu 那裡找到了一個有趣的答案(第二個答案)。
該腳本有效,但有兩個問題:
- 文件名中帶有空格:名稱被空格截斷。和
- 文件名中帶有apos (')
腳本 (rename-identical-files.awk) 是
/^total/ {next} # Skip the first line (which contains the total, of ls -l) { if (name[$5] == "") { name[$5] = $NF print "# File of size", $5, "should be named", $NF } else { printf "mv '%s' '%s'\n", $NF, name[$5] } }
它是從命令行呼叫的(在目標文件夾中):
awk -f ~/rename-identical-files.awk <(ls -l /model-folder-path) <(ls -l) | sh
問題似乎是ls命令,它(至少)對文件名中的空格和其他字元有限制。
我應該寫什麼程式碼來避免空格(和撇號)問題?
是的,沒有簡單的方法來解析
ls
可靠的輸出。在這裡,您可以
zsh
改用:#! /bin/zsh - zmodload zsh/stat || exit typeset -A size_to_name model_folder=${1?} for f in $model_folder/*(ND.); do stat -LA size +size -- $f && size_to_name[$size]=$f:t && print -r "# File of size $size should be named ${(q)f:t}" done for f in *(ND.); do stat -LA size +size -- $f && (($+size_to_name[$size])) && [[ $f != $size_to_name[$size] ]] && print -r mv -i -- ${(qq)f} ${(qq)size_to_name[$size]} done
(執行為
that-script /model-folder-path
)無論文件名可能包含哪些字元或非字元,哪個應該可以正常工作。
sh
一旦你驗證它是正確的,管道到。請注意,我們不檢查兩個文件具有相同大小的情況。在這種情況下,將選擇詞法順序中的最後一個(如果a
並且z
兩者在 model_folder 中的大小為 42,那麼任何大小為 42 的文件都將重命名為z
目前文件夾中的文件(儘管-i
這會讓您有機會避免用第二))。