web-dev-qa-db-ja.com

数値順にファイルをリストする

log1からlog164までのファイルがたくさんあります。

UNIX端末でディレクトリ(ソート済み)を一覧表示しようとしていますが、ソート関数は次のような形式のみを提供しています:

home:logs Home$ ls -1 | sort
log1.gz
log10.gz
log100.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
...etc

私が欲しいのは

home:logs Home$ ls -1 | sort
log1.gz
log2.gz
log3.gz
log4.gz
log5.gz
log6.gz
log7.gz
...{more here}
log99.gz
log100.gz
log101.gz
log102.gz
...etc

これを行うために使用できることについて何か提案はありますか?

134
Rabiani

bashの中括弧、{}、それらを順番に列挙します:

for file in log{1..164}.gz; do
    process "$file"
done
40
Kevin

この特定のケースで組み込みls機能を使用しないのはなぜですか。

-v natural sort of (version) numbers within text

例えば ​​ls -1v log*

293
lik

GNU ls(つまり、Linux、Cygwin、またはGNU lsが特別にインストールされている他のシステム)の場合):

ls -v

Zshの場合:

echo *(n)

他のシェルでは:

echo log?.gz log??.gz log???.gz

各ファイル名を別々の行にしたい場合は、echoprintf '%s\n'に置き換えます。

ファイルのメタデータも必要な場合(ls -l)にGNU lsがない場合は、ファイル名ごとに個別にlsを呼び出す必要があります。または辞書式順序で表示するファイル名のグループ。

ls -ld log?.gz; ls -ld log??.gz; ls -ld log???.gz

これらの問題を回避するには、ファイル名に十分な先行ゼロを使用して、辞書式ソートが人間にわかりやすいようにします(log001.gzなど)。

ソリューションls -1vはこの特定のケースで確かに最も優れていますが、元の質問のようにsortで機能するソリューションを用意することも良いと思います。これは、入力が来ない場合にも機能するためです。 lsから。この場合、以下を使用できます。

ls -1 | sort -n -k1.4

-nオプションは、sortに数値でソートするよう指示し、-k 1.4は、4番目の文字から最後まで、最初のフィールド(この場合はファイル名全体)にソートキーを設定します。

29
Elmar Zander

GNU sort(Linuxで利用可能))は、「バージョンソート」モードを備えており、非数値内の数値を、ユーザーが希望する方法で解釈します。

man 1 sortから:

    -V, --version-sort
           natural sort of (version) numbers within text

(リストする空のテストファイルを作成しています:
touch log1.gz log2.gz log3.gz log99.gz log100.gz log101.gz log102.gz

あなたの例の場合、-Vオプション(または--version-sort)を追加します。

ls -1 log*.gz | sort -V
log1.gz
log2.gz
log3.gz
log99.gz
log100.gz
log101.gz
log102.gz
24
Volker Siegel

macまたはBSDを使用している場合は、次のことを試してください。

ls -1 *.jpg | sort -n
8

私のバージョンのSolarisはls -v(grrr)をサポートしていません。また、上記のソートソリューションでは、1)ファイル名の数字の位置に関する知識が必要であり、2)マルチパートバージョン番号などを処理しません。

以下のアプローチはSolaris互換で、桁位置を事前に認識する必要がなく、2、3、または4つのコンポーネント(a-1.2、foo-5.6.7、bar_baz_9.10.11.12など)でバージョン番号を処理します。また、sort -fを使用して大文字と小文字を折りたたみ、ファイルと混在するディレクトリを適切に処理します。

ls -d | sort -f -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n

このバージョンでは、最初のコンポーネントが1桁に制限されていることに注意してください。

ターゲットのオペレーティングシステムがls -vをサポートしている場合、それは明らかに優れたソリューションです。

3
MykennaC

Perlソリューション:

ls log*.gz | Perl -ne 'sub getnum{ $_[0] =~ /log(\d+)\.gz/; $1 }; Push @A, $_; END{ print sort { getnum $a <=> $b } @A}'
1
$ ls
log101.gz  log102.gz  log103.gz  log104.gz  log105.gz  log106.gz  log10.gz  log1.gz
$ ls | sort -t . -n -k1.4
log1.gz
log10.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
1
kjohri

これでうまくいきました。

ファイルがあります1.jpg 2.jpg ... 18.jpg

_$ echo *.jpg | tr -s ' ' '\n' | sort -n_

sortは、印刷できないカラー文字が原因でls出力と混同されています。これを試してみると:

_ls -1 --color=none *.jpg | sort -n_

それは完全に動作します。

sortは、_-i_オプションを使用して印刷できない文字を無視できますが、それでも機能せず、理由がわかりません。

しかし、いつでもこのように色を取り除くことができ、sortは機能します。

ls -1 --color=always *.jpg | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sort -n

いつかsortがこれを選択できるようになることを願っています。

0
cy8g3n