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
これを行うために使用できることについて何か提案はありますか?
bash
の中括弧、{}
、それらを順番に列挙します:
for file in log{1..164}.gz; do
process "$file"
done
この特定のケースで組み込みls
機能を使用しないのはなぜですか。
-v natural sort of (version) numbers within text
例えば ls -1v log*
GNU ls(つまり、Linux、Cygwin、またはGNU lsが特別にインストールされている他のシステム)の場合):
ls -v
Zshの場合:
echo *(n)
他のシェルでは:
echo log?.gz log??.gz log???.gz
各ファイル名を別々の行にしたい場合は、echo
をprintf '%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番目の文字から最後まで、最初のフィールド(この場合はファイル名全体)にソートキーを設定します。
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
macまたはBSDを使用している場合は、次のことを試してください。
ls -1 *.jpg | sort -n
私のバージョンの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
をサポートしている場合、それは明らかに優れたソリューションです。
Perlソリューション:
ls log*.gz | Perl -ne 'sub getnum{ $_[0] =~ /log(\d+)\.gz/; $1 }; Push @A, $_; END{ print sort { getnum $a <=> $b } @A}'
$ 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.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
がこれを選択できるようになることを願っています。