Shell

使用排序時如何固定某些文件?

  • March 6, 2016

通常我對 Unix 命令和管道更有創意,但今天不行。

所以我所擁有的是:

collage.jpg
DCIM001.jpg
DCIM002.jpg

或這個:

001.jpg
002.jpg
boston-collage.jpg

或者有時

panama-collage.jpg
DCIM001.jpg
DCIM002.jpg

所以現在我使用這個命令,它可以正確地對圖像進行排序。

find "Image Folder" -print0 | sort -z | tar cv --no-recursion --null -T -

但我想修復帶有 collage. 的文件作為排序結果的第一個文件,以便首先將它們添加到我正在從該列表創建的 tar 存檔中。任何的想法?

如果最終目標是以所需的順序將文件放入存檔中,那麼一個簡單的解決方案是創建一個存檔,其中首先要排序的文件,然後將最後排序的文件添加到現有存檔中。這當然可以推廣到兩個以上的排序段。這需要創建一個存檔文件,您不能附加到管道中的存檔。

tar cf foo.tar /images/*collage.*
find /images ! -name '*collage.*' -print0 | sort -z | tar rf foo.tar --null -T -

如果您想僅使用基本實用程序執行自定義排序,一種可能的方法是在行中添加一個前綴,指示該項目屬於哪個組。按照您希望對組進行排序的順序排列要排序的前綴標籤,然後去除這些前綴。

find /images -print0 |
sed -z -e 's/.*collage\./1&/' -e 't' -e 's/^/2/' |
sort -z |
sed -z 's/^.//' |
tar …

另一種方法是用另一種語言(例如 Perl、Python 或 Ruby)進行排序,您可以在其中表達自定義排序。如果你這樣做,你可以用那種語言收集文件名,甚至製作檔案。這是一個僅進行排序的 Perl 範例:

perl -e '$,=$\="\0"; print sort {
   $a =~ /collage\./ ? $b =~ /collage\./ ? $a cmp $b : 1 :
                       $b =~ /collage\./ ? -1 : $a cmp $b
 } @ARGV' /images/* | tar …

另一個通過臨時重寫進行排序的範例(在 Perl 社區中稱為“Schwarztian 變換”):

perl -e '$,=$\="\0"; print
   map {substr($_,1)}
   sort
   map {$_ = (/collage\./ ? "1" : "2") . $_}
   @ARGV' /images/* | tar …

如果文件名的組合長度超過命令行長度限制,這兩個範例都將失敗。為了避免這種情況,讓 Perl 生成文件名。

perl -e '$,=$\="\0"; print
   map {substr($_,1)}
   sort
   map {$_ = (/collage\./ ? "1" : "2") . $_}
   glob("/images/*")' /images/* | tar …

如果您需要遞歸生成文件名或應用一些過濾,您可以使用File::Find。如果要在 Perl 中生成存檔,可以使用Archive::Tar

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