2012-03-31 65 views
2

我在一個目錄中。有兩個子目錄,我想按照數字順序列出它們中的文件。在第一個目錄中,這些文件被命名爲01,02,03 ...並且它們排序良好。但在第二個目錄中,文件被命名爲1,2,3,因此10種的1鍵控之前似乎並沒有工作,因爲我是從目錄中的文件回來,所以腳本像這樣:Bash - 數字排序前1s排序10s

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

不工作。我如何以真正的數字順序列出?

+2

請出示了一下樣本數據(在)和想要的結果。只需3到5行。 – 2012-03-31 12:39:46

+0

同意userunknown。這工作得很好:'echo -e '10 \ n1 \ n11 \ n2'| sort -k 1 -n' – Patrick 2012-03-31 15:00:41

+0

您指定的關鍵字段可能不是您認爲的關鍵字段。 分析find「$ PWD」-type f的輸出,看看最終結果是否真的是數字鍵的開始。 – pizza 2012-03-31 20:19:01

回答

2

排序手冊:Sort numerically: the number begins each line ... 我懷疑find的輸出是如此。因此,您應該編寫一個腳本,從文件名中除去前導字符,然後調用排序。

例如find "$WORD" -type f | cut -d/-f 2-將工作在排序中數值第一級目錄中的文件名,但其餘的將不被作爲數字排序。

您必須根據需要編寫腳本,但如果您要查找的內容位於單個目錄中,則上面的行會執行。

0

您提出了一個有趣的挑戰。試試這個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的喜歡。 txtdir/stem000010.txt將其與其他文件名進行比較之前。

0

這可能會爲你工作:

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