
我有一堆文件,全部命名如下:
name_file-1.txt
name_file-2.txt
name_file-3.txt
some_other_file-1.txt
some_other_file-2.txt
有數千種不同的文件名,有些-1.txt
最後只有一個,有些帶有-1.txt
, -2.txt
...-60.txt
我需要複製每個文件的最大編號,因此name_file-3.txt
, some_other_file-2.txt
。如何在 Linux 命令列上執行此操作?
答案1
和zsh
:
typeset -A greatest
for f (*-*(n)) greatest[${f%-*}]=$f
cp -- $greatest /destination
*-*(n)
:名稱包含-
(*-*
) 的非隱藏文件,依數字排序((n)
glob 限定符)。${f%-*}
:檔案名稱的一部分,直到最右邊-
(如果沒有,則到最後-
)。$greatest
: 擴展到非空價值觀的關聯數組。所以這裡,對於共享相同根目錄的文件,只有編號最大的文件才會被擴展。
答案2
files=(*)
mapfile -t prefixes < <(printf "%s\n" "${files[@]%-*}" | sort -u)
for p in "${prefixes[@]}"; do ls -v "$p"* | tail -1; done
name_file-3.txt
some_other_file-2.txt
然後將它們複製到其他目錄:
for ...; done | xargs cp -t /destination/directory
答案3
如果檔案位於目前工作目錄中且它們的名稱符合範例(數字前面有一個破折號),則以下符合 POSIX 標準的管道應該可以運作:
ls | sort -t- -k1,1 -k2,2rn | awk -F- 'k!=$1 {print; k=$1}' | pax -rw /path/to/dir
如果排序的 -u 選項穩定,則 awk 元件可以替換為 sort -u(以便始終選擇集合的第一行來表示該集合)。 POSIX 不需要這種穩定性,但根據其手冊,{Free,Net,Open}BSD 和 GNU 實作提供了這種穩定性。如果你喜歡誘人的命運:
ls | sort -t- -k1,1 -k2,2rn | sort -mut- -k1,1 | pax -rw /path/to/dir
無論哪種情況,目標目錄都不能位於目前工作目錄中。
答案4
我將文件拆分為製表符分隔的部分,以便進行更可靠、可自訂的文件名解析,然後使用 awk 查找每個部分的最高排名並進行報告。在繼續下一步之前,請先嘗試管道的每個部分!
find DIR -type f <other find criteron> -print |
perl -lne 'print join("\t",(/^(.*?-)(\d+)(\.\w+)$/))' |
awk -F\\t '$2 > f[$1] { f[$1]=$2;e[$1]=$3; } END { for (k in f) { print k f[k] e[k] }}' |
xargs cp -t <desination_directory>
awk 腳本將每個檔案名稱放入關聯的陣列條目中,始終保留找到的最高排名。擴展名儲存在其自己的數組中。處理完所有輸入後,將輸出所有陣列條目,每行一個。該xargs cp -t
行將所有檔案複製到您指定的目錄。
還有另一種方法行不通如果數字大於 9 並且沒有用 0 填充,那就很好。此方法按字典順序對檔案進行排序,然後在解析清單時,第一部分會發生變化,使用最近看到的檔案名稱。當檔案名稱是這樣的時候,它就不起作用:
file-9.txt
file-10.txt
因為 file-10.txt 將會出現在 file-9 之前。上面的 awk 腳本進行了數值比較。
注意:帶有製表符和換行符的檔案名稱會導致阻塞。
注意事項 2:如果每個檔案名稱前綴可以有多個副檔名,我們將必須進行一些調整以使其正確。