Saya memiliki daftar file pdf ini dalam direktori:
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
Saya ingin menggabungkan ini menggunakan ghostscript dalam urutan numerik (mirip dengan ini):
gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out.pdf *.pdf
Tetapi urutan ekspansi shell tidak mereproduksi urutan alami angka tetapi urutan alfabet:
$ 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
Bagaimana saya bisa mencapai urutan yang diinginkan dalam ekspansi (jika mungkin tanpa menambahkan 0
-pasangan secara manual ke nomor dalam nama file)?
Saya telah menemukan saran untuk digunakan ls | sort -V
, tetapi saya tidak bisa menggunakannya untuk kasus penggunaan khusus saya.
Jawaban:
Bergantung pada lingkungan Anda, Anda dapat menggunakan
ls -v
dengan GNU coreutils, misalnya:Atau jika Anda menggunakan FreeBSD atau OpenBSD versi terbaru:
sumber
ls -v
akannatural sort of (version) numbers within text
sehingga dapat digunakan juga ...-V
Fitursort
juga tidak ditentukan oleh POSIX. Namun, tampaknya telah menyebar lebih jauh, misalnya FreeBSD dan OpenBSDsort
mendukungnya.ls
digunakan saya memeriksa apakah ada pilihan dengan sendirinya daripada pipa untuk mengurutkan :)Sekali lagi, kualifikasi global zsh datang untuk menyelamatkan.
sumber
Jika semua file yang dimaksud memiliki awalan yang sama (yaitu, teks sebelum nomor;
c
dalam hal ini), Anda dapat menggunakanc?.pdf
mengembang kec0.pdf
c1.pdf
...c9.pdf
.c??.pdf
memperluas kec10.pdf
c11.pdf
...c20.pdf
(dan hinggac99.pdf
, sebagaimana berlaku). Sementara setiap kata baris perintah yang berisi karakter ekspansi pathname diperluas ke daftar nama file yang diurutkan (disusun) sesuai denganLC_COLLATE
variabel, daftar yang dihasilkan dari perluasan wildcard yang berdekatan (gumpalan) tidak digabungkan; mereka hanya digabungkan. (Sepertinya saya ingat bahwa halaman shell manual pernah menyatakan ini secara eksplisit, tetapi saya tidak dapat menemukannya sekarang.)Tentu saja jika file dapat naik
c999.pdf
, Anda harus menggunakanc?.pdf c??.pdf c???.pdf
. Memang, ini bisa membosankan jika Anda memiliki banyak digit. Anda bisa menyingkatnya sedikit; misalnya, untuk (hingga) lima digit, Anda dapat menggunakanc?{,?{,?{,?{,?}}}}.pdf
. Jika daftar nama file Anda jarang (misalnya, ada ac0.pdf
dan ac12345.pdf
, tetapi tidak harus setiap angka di antaranya), Anda mungkin harus mengaturnullglob
opsi. Kalau tidak, jika (misalnya) Anda tidak memiliki file dengan angka dua digit, Anda akan mendapatkanc??.pdf
argumen literal yang diteruskan ke program Anda.Jika Anda memiliki beberapa prefiks (misalnya, , , dan , dengan angka satu atau dua digit), Anda dapat menggunakan jelas, pendekatan kekerasan:
a<number>.pdf
b<number>.pdf
c<number>.pdf
atau runtuh ke
{a,b,c}?{,?}.pdf
.sumber
ls
,stat
, atau apa pun; dan juga bekerja di bash seperti yang diminta.Jika tidak ada kesenjangan , hal-hal berikut ini bisa membantu (walaupun samar dan tidak kuat tentang kasus tepi dan umum) - hanya untuk mendapatkan ide:
Jika ada mungkin kesenjangan, beberapa
[ -f c${i}.pdf ]
cek dapat ditambahkan.Sunting juga lihat jawaban ini , yang menurut Anda dapat (menggunakan Bash) gunakan
sumber
"$FILES"
dan"$i"
) kecuali Anda memiliki alasan yang baik untuk tidak melakukannya, dan Anda yakin Anda tahu apa yang Anda lakukan. (Sebaliknya, sementara kawat gigi bisa penting, mereka tidak sepenting tanda kutip, jadi, misalnya,"c$i.pdf"
cukup baik.) Perintah seperti , di mana berisi daftar file yang dipisahkan ruang, mungkin tampak seperti alasan yang baik untuk gunakan tanpa mengutipnya (karena tidak akan berfungsi dalam konteks itu). … (Lanjutan)gs [
…args…
] $FILES
$FILES
$FILES
"$FILES"
FILES=("c0.pdf")
danFILES+=("c$i.pdf")
); juga jawaban ini , yang menggunakan teknik yang saya sarankan.Hanya mengutip dan memperbaiki jawaban Thor ... JANGAN PERNAH menguraikan!
Anda dapat menggunakan
sort -V
(ekstensi non-POSIX untuk mengurutkan):(untuk beberapa perintah, tampaknya untuk gs adalah perintah seperti itu, Anda perlu "./ " bukannya " " ... jika yang satu tidak berfungsi, coba yang lain)
sumber
stat
tetapi menambahkan beberapa isu lainnya (seperti masalah dengan nama file mulai dengan-
, masalah jika ada terlalu banyak file,stat
menjadi perintah non-portabel). Dan karena Anda menggunakan operator split + glob tanpa menyesuaikan IFS atau menonaktifkan gumpalan, Anda masih akan memiliki masalah dengan nama file dengan spasi atau tab atau karakter wildcard.sort -V
andal, Anda akan perlu${(z)"$(printf '%s\0' * | sort -zV)"}
dizsh
(meskipunzsh
memiliki(n)
untuk jenis numerik sudah) ataureadarray -td '' files < <(printf '%s\0' * | sort -zV)
dibash4.4+
.ls
sendiri (yang tanpa -l), apa yang menjadi perhatian lain ? Perhatikan bahwa--
tidak akan membantu untuk file yang dipanggil-
.touch \"test\"; ls -1
misalnya menunjukkan'"test"'
pada ls saya. Ini tidak dimaksudkan untuk diuraikan ... ini adalah antarmuka pengguna, bukan perintah skrip.