Sayısal Sırada Glob


27

Bu dizinde pdf dosyalarının listesi var:

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

Bunları ghostscript kullanarak sayısal sırayla birleştirmek istiyorum (şuna benzer):

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

Ancak, kabuk genişleme sırası, sayıların doğal sırasını değil, alfabetik sırayı yeniden üretir.

$ 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

Genişlemede istenen sırayı nasıl elde edebilirim (eğer mümkünse 0dosya adlarındaki sayılarla el ile-ekleme yapmadan)?

Kullanmak için öneriler buldum ls | sort -V, ancak kendi özel kullanım durumum için çalışmasını sağlayamadım.


Sen olabilir alfabetik sıra numara sırasına maç olacak bu yüzden sadece, her durumda iki haneli numaralarını kullanın. İşleri zor yoldan yapmak istemiyorsan.
Wildcard

1
En az 3 haneli numara! Y2K'yı hatırla.
waltinator

Yanıtlar:


12

Ortamınıza bağlı olarak ls -vGNU coreutils ile kullanabilirsiniz , örneğin:

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

Veya FreeBSD veya OpenBSD’nin son sürümlerinde iseniz:

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

ls -vo natural sort of (version) numbers within textkadar da kullanılabilir ...
Sundeep

@Sundeep: Gerçekten, ama bu GNU coreutils'in tek çözümü gibi görünüyor.
Thor,


1
@Sundeep: Bu -Vözellik sortPOSIX tarafından da belirtilmemiş. Ancak, daha uzağa yayılmış gibi görünüyor, örneğin hem FreeBSD hem de OpenBSD sortbunu destekliyor.
Thor,

oh tamam, cevaplamak için bu detayları ekleyebilir misiniz? Benzer bir problemi ararken (sayısal sırada glob) bu ​​soruna rastladım ve lskullanılmış olduğunu görünce borulama yerine kendi başına bir seçenek olup olmadığını kontrol ettim :)
Sundeep


12

Söz konusu tüm dosyalar aynı ön eke sahipse (örneğin, numaradan önceki metin; cbu durumda),

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

c?.pdfc0.pdf c1.pdf… 'ya genişler c9.pdf.  ... 'e kadar c??.pdfgenişler (ve geçerliyse). Yol adı genişletme karakterlerini içeren her komut satırı sözcüğü değişkene göre sıralanan (harmanlanmış) bir dosya listesi listesine genişletilirken, bitişik joker karakterlerin (globların) genişlemesinden kaynaklanan listeler birleştirilmez; Onlar basitçe birleştirildi. (Shell man sayfasının bir zamanlar bunu açıkça ifade ettiğini hatırlıyor gibiyim ama şimdi bulamıyorum.)c10.pdf c11.pdfc20.pdfc99.pdfLC_COLLATE

Tabiki dosyalar gidebiliyorsa c999.pdfkullanmalısınız c?.pdf c??.pdf c???.pdf. Kuşkusuz, çok fazla haneniz varsa, bu can sıkıcı olabilir. Biraz kısaltabilirsiniz; örneğin, (en fazla) beş hane için kullanabilirsiniz c?{,?{,?{,?{,?}}}}.pdf. Dosya adları listeniz seyrekse (örneğin, a c0.pdfve a vardır c12345.pdf, ancak bunların arasında her sayı olması gerekmez), muhtemelen nullglobseçeneği ayarlamanız gerekir . Aksi takdirde, (örneğin) iki basamaklı sayılar içeren bir c??.pdfdosyanız yoksa, programınıza gerçek bir argüman iletirsiniz.

Birden önekleri (örneğin varsa , ve , bir veya iki basamaklı sayıları ile birlikte), bariz, kaba kuvvet yaklaşımı kullanabilirsiniz:a<number>.pdfb<number>.pdf c<number>.pdf

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

veya onu daraltın {a,b,c}?{,?}.pdf.


1
Bunun kabataslak kullanımı olduğu iddia ötesinde, çünkü bu en iyi yanıtı ls, statbaşka, ya da bir şey; ve istendiği gibi bash olarak da çalışır.
Kyle

5

Herhangi bir boşluk yoksa , aşağıdakiler yararlı olabilir (kabataslak olsa ve kenar davalar ve genelliğe ilişkin sağlam olmasa da) - sadece bir fikir edinmek için:

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

Orada ise olabilecek boşluklar bazı [ -f c${i}.pdf ]çek eklenebilir.

Düzenle , bu cevabı da görebildiğinize göre (Bash kullanarak)

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

Kabuk değişkeni referanslarınızı (örneğin "$FILES"ve "$i") alıntı yapmamak için iyi bir nedeniniz olmadığı ve ne yaptığınızı bildiğinizden emin olmadığınız sürece , genellikle iyi bir fikirdir . (Parantez önemli olabilir iken aksine, bu kadar, örneğin tırnak kadar önemli değiliz "c$i.pdf"yeterince iyidir.) Gibi bir komut , dosyaların bir boşlukla ayrılmış listesini içeren, iyi bir sebep gibi görünse alıntı yapmadan kullanın (çünkü bu bağlamda çalışmaz). … (Devam ediyor)gs  [ …args… ]  $FILES$FILES$FILES"$FILES"
G-Man 20: 19'da 'Monica'yı Yeniden Girin'

(Devam)… Fakat bkz . Bash / POSIX kabukları içindeki bir değişkeni , özellikle de benim cevabımdaki bash / POSIX kabuklarındaki bir değişkeni alıntılamayı unutma güvenlik sonuçları ; (örneğin, FILES=("c0.pdf")ve FILES+=("c$i.pdf")) Ayrıca önerdiğim tekniği kullanan bu cevabı da .
G-Man

1

Sadece Thor'un cevabını alıntı ve sabitleme ... ASLA ayrıştırma!

Kullanabilirsiniz sort -V(sıralamak için POSIX dışı bir uzantı):

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

(bazı komutlar için, görünüşe göre gs için böyle bir komuttur, bir " işe yaramazsa, diğerini deneyin " yerine "./ " gerekir )


1
Değil ayrıştırma ls çıktı yapmak olduğunu ls ekranlara çünkü dosya adları yeni satır ayrılmış satır bir dosya adı herhangi geçerli gibidir, ancak burada aynı şeyi yaparken statdosya adları başlayan ile ilgili sorunlar gibi (birkaç diğer konular ama ekleyerek ile -, çok fazla dosya varsa, sorunun statolmayan bir taşınabilir komut olmak üzere). Ve split + glob operatörünü IFS'yi ayarlamadan veya globları devre dışı bırakmadan kullandığınız için, boşluk veya sekme veya joker karakterli dosya adlarıyla ilgili sorunlarınız hala devam eder.
Stéphane Chazelas

GNU'yu kullanmak için sort -Vgüvenilir, Size gereken tek şey ${(z)"$(printf '%s\0' * | sort -zV)"}de zsh(gerçi zshvardır (n)zaten sayısal sıralama için) veya readarray -td '' files < <(printf '%s\0' * | sort -zV)içinde bash4.4+.
Stéphane Chazelas

@ StéphaneChazelas teşekkürler, ve newline'ın bir endişe kaynağı olabileceği konusunda haklısınız, ancak ls'yi ayrıştırmamak için tek neden bu değil. Ve evet, tembeldim ve eklemedi. Ama ben printf kullanmalıydım ... Bunu değiştireceğim.
Peter,

için ls, (yani -l olmadan) tek başına ya bunlar ne diğer endişeler ? Bunun --adı verilen bir dosya için yardımcı olmayacağını unutmayın -.
Stéphane Chazelas

@ StéphaneChazelas, sürümler arasında başka farklılıklar var ... orada "total 0" yazıyor gibi, ve en yeni sürümler, onları istemediğiniz şeylerin etrafında bile alıntılar yapıyor ... touch \"test\"; ls -1mesela '"test"'benim ls. Sadece ayrıştırılmaya niyetli değil ... bir kullanıcı arayüzüdür, bir komut dosyası komutu değildir.
Peter,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.