【问题标题】:Bash - numerical sort sorts 10s before 1sBash - 数字排序在 1s 之前排序 10s
【发布时间】:2012-03-31 12:26:30
【问题描述】:

我在一个目录中。有两个子目录,我想按数字顺序列出其中的文件。在第一个目录中,文件被命名为 01、02、03... 并且它们排序良好。但是在第二个目录中,文件被命名为 1、2、3,因此在 1 之前有 10 个排序。键控似乎不起作用,因为我是从文件返回的目录,所以像这样的脚本:

find "$PWD" -type f|sort -n -t _ -k 1

不起作用。如何按真正的数字顺序列出?

【问题讨论】:

  • 请显示一些样本数据(in)和期望的结果。只需 3 到 5 行。
  • 同意用户未知。这工作得很好:echo -e '10\n1\n11\n2' | sort -k 1 -n
  • 您指定的关键字段可能不是您认为的那样。分析 find "$PWD" -type f 的输出,看看你最终得到的是一个数字键的开头。

标签: bash sorting numerical


【解决方案1】:

排序手册:Sort numerically: the number begins each line ... 我怀疑 find 的输出是否会如此。因此,您应该编写一个脚本,从文件名中去除前导字符,然后调用 sort。

例如find "$WORD" -type f | cut -d / -f 2- 将按数字对第一级目录中的文件名进行排序,但其余的不会按数字排序。

您必须根据需要编写脚本,但是如果您要查找的内容在单个目录中,则上面的行就可以了。

【讨论】:

    【解决方案2】:

    你提出了一个有趣的挑战。试试这个 Perl 脚本:

    #!/usr/bin/perl
    use warnings;
    use strict;
    use integer;
    
    # This script sorts filenames while respecting their ordinal component,
    # outputting 'dir/stem9.ext' before 'dir/stem10.ext'.  As input, it
    # expects one filename per line on stdin.
    
    our $n_digits = 6;
    
    sub compare_filenames_ordinally ($$) {
        my ($a, $b) = @_;
        my $pattern = qr|^(.*?)(\d*)((?:\.[^/\d]*)?)$|;
        my ($stem_a, $ordinal_a, $extension_a) = $a =~ /$pattern/;
        my ($stem_b, $ordinal_b, $extension_b) = $b =~ /$pattern/;
        length($ordinal_a) <= $n_digits && length($ordinal_b) <= $n_digits
          or die "$0: the ordinal part of the filename "
          . "is longer than $n_digits digits\n";
        my $ordinal_a1 = length($ordinal_a)
          ? sprintf "%0${n_digits}d", $ordinal_a : '';
        my $ordinal_b1 = length($ordinal_b)
          ? sprintf "%0${n_digits}d", $ordinal_b : '';
        my $a1 = "${stem_a}${ordinal_a1}${extension_a}";
        my $b1 = "${stem_b}${ordinal_b1}${extension_b}";
        return $a1 cmp $b1;
    }
    
    my @file = <>;
    chomp for @file;
    @file = sort { compare_filenames_ordinally $a, $b } @file;
    print "$_\n" for @file;
    

    该脚本无疑可以改进,尤其是因为它重复了一些关于 $a$b 的代码行,但它的想法是它扩展了 dir/stem10.txt 之类的代码 em> 到 dir/stem000010.txt,然后再将其与其他文件名进行比较。

    【讨论】:

      【解决方案3】:

      这可能对你有用:

      mkdir test
      cd test
      mkdir t1 t2
      cd t1
      seq -f 'test_%02g.txt 20 | xargs touch
      cd ../t2
      touch test_{1..20}.txt
      cd ..
      find . -type f | sort -t_ -k1,1 -k2,2g
      ./t1/test_01.txt
      ./t1/test_02.txt
      ./t1/test_03.txt
      ./t1/test_04.txt
      ./t1/test_05.txt
      ./t1/test_06.txt
      ./t1/test_07.txt
      ./t1/test_08.txt
      ./t1/test_09.txt
      ./t1/test_10.txt
      ./t1/test_11.txt
      ./t1/test_12.txt
      ./t1/test_13.txt
      ./t1/test_14.txt
      ./t1/test_15.txt
      ./t1/test_16.txt
      ./t1/test_17.txt
      ./t1/test_19.txt
      ./t1/test_20.txt
      ./t2/test_1.txt
      ./t2/test_2.txt
      ./t2/test_3.txt
      ./t2/test_4.txt
      ./t2/test_5.txt
      ./t2/test_6.txt
      ./t2/test_7.txt
      ./t2/test_8.txt
      ./t2/test_9.txt
      ./t2/test_10.txt
      ./t2/test_11.txt
      ./t2/test_12.txt
      ./t2/test_13.txt
      ./t2/test_14.txt
      ./t2/test_15.txt
      ./t2/test_16.txt
      ./t2/test_17.txt
      ./t2/test_18.txt
      ./t2/test_19.txt
      ./t2/test_20.txt
      

      或者这个:

      find . -type f | 
      sed 'h;s/.*\//& /;H;s/.* //;s/[^0-9]//g;x;G;s/\n/ /g' |
      sort -k2,2 -k4,4g |
      cut -d' ' -f1
      ./t1/test_01.txt
      ./t1/test_02.txt
      ./t1/test_03.txt
      ./t1/test_04.txt
      ./t1/test_05.txt
      ./t1/test_06.txt
      ./t1/test_07.txt
      ./t1/test_08.txt
      ./t1/test_09.txt
      ./t1/test_10.txt
      ./t1/test_11.txt
      ./t1/test_12.txt
      ./t1/test_13.txt
      ./t1/test_14.txt
      ./t1/test_15.txt
      ./t1/test_16.txt
      ./t1/test_17.txt
      ./t1/test_19.txt
      ./t1/test_20.txt
      ./t2/test_1.txt
      ./t2/test_2.txt
      ./t2/test_3.txt
      ./t2/test_4.txt
      ./t2/test_5.txt
      ./t2/test_6.txt
      ./t2/test_7.txt
      ./t2/test_8.txt
      ./t2/test_9.txt
      ./t2/test_10.txt
      ./t2/test_11.txt
      ./t2/test_12.txt
      ./t2/test_13.txt
      ./t2/test_14.txt
      ./t2/test_15.txt
      ./t2/test_16.txt
      ./t2/test_17.txt
      ./t2/test_18.txt
      ./t2/test_19.txt
      ./t2/test_20.txt
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-24
        • 2021-10-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多