web-dev-qa-db-ja.com

ファイル名の一部でファイルを並べ替える方法は?

以下のファイルがあるとします:

ABC38388.SC01.StatueGrade_MKP
ABC38388.SC02.Statue_GKP
DEF38389.SC03.Statue_HKP
XYZ38390.SC00.Statue_WKP

次のように、SCの値に基づいてすべてを一覧表示するにはどうすればよいですか。

XYZ38390.SC00.Statue_WKP
ABC38388.SC01.StatueGrade_MKP
ABC38388.SC02.Statue_GKP
DEF38389.SC03.Statue_HKP
7
MRKR

ファイル名に空白やその他の奇妙な文字が含まれていないこの特定のケースでは、lsを使用してsortにパイプすることができます。

$ ls -d -- *.SC* | sort -t. -k2
XYZ38390.SC00.Statue_WKP
ABC38388.SC01.StatueGrade_MKP
ABC38388.SC02.Statue_GKP
DEF38389.SC03.Statue_HKP

-tはフィールド区切り文字を設定し、-k2sortに2で始まる行の部分に基づいてソートするように指示しますnd フィールド(2番目のフィールドには-k2,2を使用only)。

より複雑なケースでは、各ファイル名に続けてNULL文字(\0)を出力し、-zを使用してGNU sortにパイプすることができます。 NULL区切りの行を読み取るように指示し、最後にtrを使用して\0\nに戻すように指示するオプション:

printf '%s\0' *SC* | sort -zt. -k2 | tr '\0' '\n'
8
terdon

Zshでは、oeまたはo+グロブ修飾子を使用して、グロブの独自のソート順を定義できます。

ls -lUd -- *(oe['REPLY=${REPLY#*.SC}'])

または:

bysc() REPLY=${REPLY#*.SC}
ls -lUd -- *(o+bysc)

ソート関数は$REPLYでファイル名を受け取り、グロビングがソートする$REPLYで文字列を返すことを目的としています。ここでは、ファイル名の最初の.SC(または.SCが含まれていない場合は完全なファイル名)の右側の部分を返します。

4

GNUシステムで、シェルとしてzshまたはbashを使用する場合)、これを使用します。

find -maxdepth 1 -type f -print0 | sort -z -t. -k3 | \
while IFS="" read -r -d "" f; do
  basename "$f"
done

  • findは、現在のディレクトリ(-maxdepth 1)をnullバイト区切り(-print0)。
  • sortは、入力のnullバイト区切り(-z)そして、3番目のフィールド(-k3)ドット(-t.)。
  • whileは入力を読み取ります
    • basenameはパスなしで名前を出力します
1
chaos

私は-私がよくするように-Perlを提案します。

Perlには、比較関数を指定できるソート関数があります。この比較関数は、2つの値を取り、相対位置に応じて-10または1を返す任意のテストです。

リストを反復処理して、各値を$aおよび$bとして設定し、各要素に対して「テストを実行」します。

したがって、デフォルトでは:

$a cmp $b 

文字列ごとの比較の場合、または数値の場合はsort { $a <=> $b }

ただし、その結果、任意の複雑なカスタムソート基準を適用できます。

#!/usr/bin/Perl
use strict;
use warnings;

sub sort_by_sc {
   my ( $a_sc ) = $a =~ m/SC(\d+)/;
   my ( $b_sc ) = $b =~ m/SC(\d+)/;
   return $a_sc <=> $b_sc;
}


my @file_list = qw ( 
    ABC38388.SC01.StatueGrade_MKP
    ABC38388.SC02.Statue_GKP
    DEF38389.SC03.Statue_HKP
    XYZ38390.SC00.Statue_WKP
);

print sort sort_by_sc @file_list;

またはSTDINまたはファイルを読み取る1つのライナーに削減(ラインフィード区切り、通常はこれで十分です):

Perl -e 'print sort {@x = map {/SC(\d+)/}($a,$b); $x[0] <=> $x[1]} <>'

代わりに、ディレクトリパターンのglobの結果をフィードすることができます。

Perl -e 'print sort {@x = map {/SC(\d+)/}($a,$b); $x[0] <=> $x[1]} glob ( "*SC*")'
0
Sobrique