web-dev-qa-db-ja.com

数値順のグロブ

次のPDFファイルのリストがディレクトリにあります。

c0.pdf   c12.pdf  c15.pdf  c18.pdf  c20.pdf  c4.pdf  c7.pdf
c10.pdf  c13.pdf  c16.pdf  c19.pdf  c2.pdf   c5.pdf  c8.pdf
c11.pdf  c14.pdf  c17.pdf  c1.pdf   c3.pdf   c6.pdf  c9.pdf

私はこれらを番号順にghostscriptを使用して連結したいと思います(これと同様)。

gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out.pdf *.pdf

しかし、シェルの展開順序は、数字の自然な順序ではなく、アルファベット順を再現します。

$ for f in *.pdf; do echo $f; done
c0.pdf
c10.pdf
c11.pdf
c12.pdf
c13.pdf
c14.pdf
c15.pdf
c16.pdf
c17.pdf
c18.pdf
c19.pdf
c1.pdf
c20.pdf
c2.pdf
c3.pdf
c4.pdf
c5.pdf
c6.pdf
c7.pdf
c8.pdf
c9.pdf

展開で目的の順序を実現するにはどうすればよいですか(可能であれば、ファイル名の番号に0- paddingを手動で追加せずに)?

ls | sort -Vを使用するための提案を見つけましたが、特定のユースケースで機能させることができませんでした。

30
moooeeeep

環境に応じて、ls -v with GNU coreutils、例:

gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
   -sOutputFile=out.pdf $(ls -v)

または、FreeBSDまたはOpenBSDの最新バージョンを使用している場合:

gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite \
   -sOutputFile=out.pdf $(ls | sort -V)
13
Thor

もう一度、 zshのglob修飾子 が役に立ちます。

echo *.pdf(n)

問題のすべてのファイルに同じプレフィックス(つまり、番号の前のテキスト、この場合はc)がある場合、次のように使用できます。

gs …引数…c?.pdf c ??。pdf

c?.pdfc0.pdfc1.pdfc9.pdfに展開されます。 c??.pdfc10.pdfc11.pdfc20.pdfに展開されます(該当する場合はc99.pdfまで)。パス名展開文字を含む各コマンドラインWordは、LC_COLLATE変数に従ってソート(照合)されたファイル名のリストに展開されますが、隣接するワイルドカード(グロブ)の展開の結果であるリストはマージされません;それらは単に連結されます。 (Shellのmanページでこれが明示的に述べられていたことを思い出したようですが、今は見つかりません。)

もちろん、ファイルがc999.pdfに達する場合は、c?.pdf c??.pdf c???.pdfを使用する必要があります。確かに、桁数が多い場合、これは退屈な作業になる可能性があります。少し省略できます。たとえば、(最大)5桁の場合、c?{,?{,?{,?{,?}}}}.pdfを使用できます。ファイル名のリストがまばらである場合(たとえば、c0.pdfc12345.pdfがありますが、必ずしもその間にすべての数があるわけではありません)、おそらくnullglobオプションを設定する必要があります。それ以外の場合、(たとえば)2桁の番号のファイルがない場合は、リテラルc??.pdf引数がプログラムに渡されます。

複数のプレフィックスがある場合(例:a<number>.pdfb<number>.pdf、およびc<number>.pdf、1桁または2桁の数字)、明白なブルートフォースアプローチを使用できます。

a?.pdf a??.pdf b?.pdf b??.pdf c?.pdf c??.pdf

または{a,b,c}?{,?}.pdfに折りたたみます。

ギャップがない場合、次の情報が役立つ可能性があります(ただし、エッジケースと一般性に関して大雑把ではなく堅牢ではありません)。

FILES="c0.pdf"
for i in $(seq 1 20); do FILES="${FILES} c${i}.pdf"; done
gs [...args...] $FILES

ギャップがあるかもしれない場合、いくつかの[ -f c${i}.pdf ]チェックを追加できます。

Editも参照してください この答え (Bashを使用して)

gs [..args..] c{1..20}.pdf
5
sr_