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

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

通常我对 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

相关内容