Ich habe diese Liste von PDF-Dateien in einem Verzeichnis:
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
Ich möchte diese mit Ghostscript in numerischer Reihenfolge verketten (ähnlich wie folgt):
gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out.pdf *.pdf
Die Shell-Erweiterungsreihenfolge gibt jedoch nicht die natürliche Reihenfolge der Zahlen wieder, sondern die alphabetische Reihenfolge:
$ 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
Wie kann ich die gewünschte Reihenfolge in der Erweiterung erreichen (wenn möglich ohne manuelles Hinzufügen von 0
-padding zu den Nummern in den Dateinamen)?
Ich habe Vorschläge zur Verwendung gefunden ls | sort -V
, konnte sie jedoch nicht für meinen speziellen Anwendungsfall zum Laufen bringen.
bash
filenames
wildcards
huhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuhuh
quelle
quelle
Antworten:
Abhängig von Ihrer Umgebung können Sie
ls -v
GNU-Coreutils verwenden, z.Oder wenn Sie auf den neuesten Versionen von FreeBSD oder OpenBSD sind:
quelle
ls -v
wirdnatural sort of (version) numbers within text
so, dass kann auch verwendet werden ...-V
Funktion vonsort
wird auch von POSIX nicht angegeben. Es scheint sich jedoch weiter verbreitet zu haben, zum Beispielsort
unterstützen es sowohl FreeBSD als auch OpenBSD .ls
als ich nach einem ähnlichen Problem suchte (Glob in numerischer Reihenfolge) und als ich es als gebraucht ansah, habe ich geprüft, ob es eine Option für sich hatte, anstatt es zu sortieren :)Einmal mehr helfen die Glob-Qualifikanten von zsh .
quelle
Wenn alle fraglichen Dateien dasselbe Präfix haben (dh der Text vor der Nummer;
c
in diesem Fall), können Sie verwendenc?.pdf
erweitert sich zuc0.pdf
c1.pdf
…c9.pdf
.c??.pdf
erweitert aufc10.pdf
c11.pdf
…c20.pdf
(undc99.pdf
gegebenenfalls auf bis). Während jedes Befehlszeilenwort, das Pfadnamen-Erweiterungszeichen enthält, zu einer Liste von Dateinamen erweitert wird, die gemäß derLC_COLLATE
Variablen sortiert (sortiert) sind, werden die Listen, die sich aus der Erweiterung benachbarter Platzhalter (Globs) ergeben, nicht zusammengeführt. Sie werden einfach verkettet. (Ich erinnere mich anscheinend, dass die Shell-Manpage dies einmal explizit angegeben hat, aber ich kann es jetzt nicht finden.)Natürlich, wenn die Dateien gehen können
c999.pdf
, sollten Sie verwendenc?.pdf c??.pdf c???.pdf
. Zugegeben, bei vielen Ziffern kann das langweilig werden. Sie können es ein wenig abkürzen; Sie können beispielsweise (bis zu) fünf Ziffern verwendenc?{,?{,?{,?{,?}}}}.pdf
. Wenn Ihre Liste der Dateinamen dünn ist (z. B. einc0.pdf
und einc12345.pdf
, aber nicht unbedingt jede Zahl dazwischen), sollten Sie dienullglob
Option wahrscheinlich festlegen . Andernfalls, wenn Sie (zum Beispiel) keine Dateien mit zweistelligen Zahlen haben, wirdc??.pdf
Ihrem Programm ein wörtliches Argument übergeben.Wenn Sie mehrere Präfixe (zB , und mit Zahlen von einer oder zwei Ziffern), können Sie das Offensichtliche, Brute - Force - Methode verwenden:
a<number>.pdf
b<number>.pdf
c<number>.pdf
oder reduzieren Sie es auf
{a,b,c}?{,?}.pdf
.quelle
ls
,stat
oder irgendetwas anderes; und funktioniert auch in bash wie gewünscht.Wenn es keine Lücken gibt , könnte sich Folgendes als hilfreich erweisen (wenn auch lückenhaft und in Bezug auf Randfälle und Allgemeingültigkeit nicht robust) - nur um sich ein Bild zu machen:
Wenn es sein kann Lücken, einige
[ -f c${i}.pdf ]
könnten Check hinzugefügt werden.Bearbeiten Sie auch diese Antwort , nach der Sie (mit Bash) verwenden könnten
quelle
"$FILES"
und"$i"
) in Anführungszeichen zu setzen, es sei denn, Sie haben einen guten Grund, dies nicht zu tun, und Sie sind sicher, dass Sie wissen, was Sie tun. (Während geschweifte Klammern wichtig sein können, sind sie nicht so wichtig wie Anführungszeichen, daher ist sie beispielsweise"c$i.pdf"
gut genug.) Ein Befehl wie , bei dem eine durch Leerzeichen getrennte Liste von Dateien enthalten ist, scheint ein guter Grund dafür zu sein Verwenden Sie, ohne es in Anführungszeichen zu setzen (da es in diesem Kontext nicht funktioniert). … (Fortsetzung)gs [
…args…
] $FILES
$FILES
$FILES
"$FILES"
FILES=("c0.pdf")
undFILES+=("c$i.pdf")
). auch diese Antwort , die die von mir vorgeschlagene Technik verwendet.Nur die Antwort von Thor zitieren und korrigieren ... NIEMALS ls analysieren!
Sie können
sort -V
(eine Nicht-POSIX-Erweiterung zum Sortieren) verwenden:(Für einige Befehle, anscheinend für gs, benötigen Sie "./ " anstelle von " " ... wenn einer nicht funktioniert, versuchen Sie den anderen)
quelle
stat
andere Dateiname. Hier tun Sie jedoch dasselbe , fügen jedoch mehrere andere Probleme hinzu (z. B. Probleme mit Dateinamen, die beginnen) with-
, Problem, wenn zu viele Dateien vorhanden sind, dastat
es sich um einen nicht portierbaren Befehl handelt). Und da Sie den split + glob-Operator verwendet haben, ohne IFS anzupassen oder Globs zu deaktivieren, treten weiterhin Probleme mit Dateinamen mit Leerzeichen, Tabulatoren oder Platzhalterzeichen auf.sort -V
zuverlässig, müssen Sie${(z)"$(printf '%s\0' * | sort -zV)"}
inzsh
(obwohlzsh
hat(n)
für die numerische Art bereits) oderreadarray -td '' files < <(printf '%s\0' * | sort -zV)
inbash4.4+
.ls
allein (das heißt ohne -l), was sind diese anderen Bedenken ? Beachten Sie, dass--
dies für eine aufgerufene Datei nicht hilft-
.touch \"test\"; ls -1
zum Beispiel zeigt'"test"'
auf meinem ls. Es ist einfach nicht dazu gedacht, analysiert zu werden ... es ist eine Benutzeroberfläche, kein Skriptbefehl.