通常我对 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 存档中。任何想法?
答案1
如果最终目标是将文件按所需顺序放入存档中,那么一个简单的解决方案是创建一个存档,其中首先要排序的文件,然后将最后排序的文件添加到现有存档中。这当然可以推广到两个以上的排序段。这需要创建一个存档文件,您无法附加到管道中的存档。
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 …
如果您需要递归生成文件名或应用一些过滤,您可以使用文件::查找。如果你想用 Perl 生成档案,你可以使用存档::焦油。
答案2
这是我的建议,使用临时文件:
tmpdir=$(mktemp)
find "Image Folder" -print0 > $tmpdir/temp
{ grep -z collage $tempdir/temp | sort -z;
grep -z -v collage $tempdir/tmp | sort -z; } | \
tar cv --no-recursion --null -T -
rm -rf $tmpdir
您可以使用更简单的临时文件,只要您不将其放入“图像文件夹”中即可。
find
该解决方案背后的基本思想是将 的结果保存到临时文件中,以便我们可以grep
对其运行两个 s,grep
在将它们组合到管道 for 之前分别对每个结果进行排序tar
。