数値順序付きグローブ


27

私はディレクトリにこの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

私はゴーストスクリプトを使用してこれらを数値順に連結します(これに似ています):

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が、特定のユースケースで機能させることができませんでした。


あなたは可能性がアルファベット順に番号順と一致しますので、ちょうど、すべての場合に2桁の数字を使用します。あなたが物事を難しい方法でやりたくない限り。
ワイルドカード

1
少なくとも3桁の数字!Y2Kを思い出してください。
ワルチネーター

回答:


12

環境に応じて、ls -vGNU 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)

ls -vされますnatural sort of (version) numbers within textので、それがうまくとして使用することができます...
Sundeep

@Sundeep:確かに、これはGNU coreutilsのみのソリューションのようです。
トール

はい、GNU固有のようです-pubs.opengroup.org/onlinepubs/9699919799
Sundeep

1
@Sundeep:の-V機能もsortPOSIXによって指定されていません。ただし、たとえばFreeBSDとOpenBSDの両方でsortサポートされているなど、さらに広がっているようです。
トール

まあ、これらの詳細を追加して回答することもできますか?同様の問題(数値順のグロブ)を検索してls使用中にこの答えに出くわしました。並べ替えるパイプの代わりにそれ自体でオプションがあるかどうかをチェックアウトしました:)
Sundeep


12

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

gs   …args…   c?.pdf c ??。pdf

c?.pdfc0.pdf c1.pdf…に展開されますc9.pdf。  … (および該当する場合、最大)にc??.pdf展開されc10.pdf c11.pdfます。パス名展開文字を含む各コマンドラインワードは、変数に従ってソート(照合)されたファイル名のリストに展開されますが、隣接するワイルドカード(グロブ)の展開から生じるリストはマージされません。それらは単純に連結されます。(シェルのmanページでこれを明示的に述べていたことを思い出すようですが、今は見つけることができません。)c20.pdfc99.pdfLC_COLLATE

もちろん、ファイルが上に行くことができるならc999.pdf、あなたは使うべきc?.pdf c??.pdf c???.pdfです。確かに、桁数が多いとこれは面倒になります。少し短縮できます。たとえば、(最大)5桁の場合、を使用できますc?{,?{,?{,?{,?}}}}.pdf。ファイル名のリストがまばらである場合(たとえば、a c0.pdfとaがc12345.pdfありますが、必ずしも間にすべての数があるわけではありません)、おそらくnullglobオプションを設定する必要があります。それ以外の場合、(たとえば)2桁の数字のファイルがない場合、リテラルc??.pdf引数がプログラムに渡されます。

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

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

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


1
それは大ざっぱの使用のいずれかの請求を超えますので、これが最良の答えであるlsstatまたは何か他のもの。また、要求に応じてbashで動作します。
カイル

5

ギャップがない場合、次のことは役に立つかもしれません(エッジケースと一般性に関しては大ざっぱで堅牢ではありませんが)-アイデアを得るためだけに:

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

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

編集すると、(Bashを使用して)使用できるこの回答も参照してください

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

一般的に、シェル変数参照(例えば、"$FILES"および"$i")を引用するのは、そうする正当な理由がない限り、良い考えです。(括弧が重要になることがありながら、これとは対照的に、彼らはそう、例えば、引用符のような重要なようじゃない"c$i.pdf"良い十分である。)のようなコマンド、ファイルのスペース区切りのリストが含まれている、との良好な理由のように見えるかもしれません引用符なしで使用します(そのコンテキストでは機能しないため)。…(続き)gs  [ …args… ]  $FILES$FILES$FILES"$FILES"
Gマンは「

(続き)...しかし、参照はbash / POSIXシェルで変数を引用し忘れるのセキュリティへの影響、特にそれに私の答えを bashで配列としてマルチワード変数を処理する方法の使用上の注意事項については、(例えば、FILES=("c0.pdf")FILES+=("c$i.pdf"))。また、この答えは、私が提案する手法を使用しています。
G-Manは「Reinstate Monica」と言います

1

Thorの答えを引用して修正するだけです... lsを解析しないでください!

次を使用できますsort -V(ソートする非POSIX拡張機能):

printf '%s\0' ./* | sort -zV \
    | xargs -0 gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH \
        -sDEVICE=pdfwrite -sOutputFile=out.pdf

(一部のコマンドでは、明らかにgsがそのようなコマンドであるため、「」ではなく「./ が必要です...一方が機能しない場合は、もう一方を試してください)


1
パースlsの出力にはない改行は、ファイル名にどのように有効なようですが、ここではあなたと同じことをやっている間、LSが表示ファイル名は改行で区切られているためであるstatが、始まるファイル名での問題のような他のいくつかの問題を(追加しますwith -、ファイルが多すぎる場合の問題、stat移植性のないコマンドです)。また、IFSを調整したり、globを無効にしたりせずにsplit + glob演算子を使用したため、スペースやタブ、ワイルドカード文字を含むファイル名の問題が引き続き発生します。
ステファンシャゼラス

GNUを使用するにはsort -V確実に、あなたが必要と思い${(z)"$(printf '%s\0' * | sort -zV)"}zsh(ただしをzsh持っている(n)か、すでに数値ソートのために)readarray -td '' files < <(printf '%s\0' * | sort -zV)bash4.4+
ステファンシャゼラス

@StéphaneChazelasに感謝します。改行が問題になることは間違いありませんが、lsを解析しない理由はそれだけではありません。そして、ええ、私は怠け者で、付け加えませんでした。しかし、printfを使用する必要がありました...それを変更します。
ピーター

以下のためにls、(つまり、-lなしで)単独のものを何他の懸念は--というファイルには役に立たないことに注意してください-
ステファンシャゼラス

@StéphaneChazelasにはバージョン間に他の違いがあります...そこに印刷された「合計0」のように、最新のlsバージョンはあなたがそれを望まないものに引用符を付けさえします... touch \"test\"; ls -1例えば'"test"'私のlsに表示されます。単に解析することを意図したものではありません...それは、スクリプトコマンドではなく、ユーザーインターフェイスです。
ピーター
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.