Bash - числовая сортировка за 10 с до 1 с - PullRequest
2 голосов
/ 31 марта 2012

Я в каталоге.Есть два подкаталога, и я хочу перечислить файлы в них, в числовом порядке.В первом каталоге файлы называются 01, 02, 03 ... и они сортируются нормально.Но во втором каталоге файлы имеют имена 1, 2, 3 и, следовательно, 10 сортировок до 1. Ключи, похоже, не работают, так как я возвращаю каталог из файлов, поэтому такой скрипт:*

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

Не работает.Как мне перечислить в истинном числовом порядке?

Ответы [ 3 ]

2 голосов
/ 31 марта 2012

Руководство по сортировке: Sort numerically: the number begins each line ... Я сомневаюсь, что вывод от find будет таким. Поэтому вы должны написать скрипт, который удаляет начальные символы из имен файлов, а затем вызывает sort.

Например, find "$WORD" -type f | cut -d / -f 2- будет работать при сортировке имен файлов в каталоге первого уровня по номерам, но остальные не будут отсортированы по номерам.

Вы должны написать сценарий в соответствии со своими потребностями, но если то, что вы ищете, находится в одном каталоге, то приведенная выше строка подойдет.

0 голосов
/ 31 марта 2012

Это может работать для вас:

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
0 голосов
/ 31 марта 2012

Вы ставите интересный вызов.Попробуйте этот 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 до dir / stem000010.txt перед сравнением его с другими именами файлов.

...