
Ich habe einen Ordner mit mehreren Dateien, die wie folgt formatiert sind:
C Block Scan copy 1.pdf
C Block Scan copy 2.pdf
C Block Scan copy 3.pdf
C Block Scan copy 4.pdf
.
.
.
Ein Problem, das ich habe, ist, dass Unix sie beim Ausführen ls
als auflistet
C Block Scan copy 1.pdf
C Block Scan copy 10.pdf
C Block Scan copy 11.pdf
C Block Scan copy 12.pdf
.
.
.
Ich möchte die Zahlen auffüllen, so dass Unix sie (hoffentlich) in der Reihenfolge auflistet, wie
C Block Scan copy 01.pdf
C Block Scan copy 02.pdf
C Block Scan copy 03.pdf
.
.
.
C Block Scan copy 09.pdf
C Block Scan copy 10.pdf
C Block Scan copy 11.pdf
C Block Scan copy 12.pdf
.
.
.
Ich habe einen Beitrag mit einem ähnlichen Problem gefunden.Auffüllen einer Zahl in einem Dateinamen auf eine feste Länge, aber ich habe versucht, ihre Lösung auf meinen Fall anzuwenden, aber es hat nicht funktioniert. Folgendes habe ich versucht:
for f in *.pdf; do
int=`basename $f .pdf | cut -d '.' -f 2`
new_name=`printf "file.%0.2i.pdf\n” $int`
[ ! -f $new_name ] && mv $f $new_name
done
Ich gebe zu, dass dies eine blinde Anpassung ihrer Lösung an meine Situation ist, was mir nicht gefällt, da ich die zugrunde liegende Syntax nicht wirklich verstehe und mein Rang bei StackExchange noch nicht hoch genug ist, um diesen Beitrag zu kommentieren.
Ich bin neu im Shell-Scripting, daher wäre eine Erklärung der Syntax hilfreich und willkommen.
Falls es hilft: Ich verwende macOS Mojave 10.14.6 und habe Brew installiert.
Dank im Voraus.
Antwort1
Mit zsh
(jetzt die Standardbenutzer-Shell unter macOS):
autoload zmv # best in ~/.zshrc
zmv '(* )([0-9].pdf)' '${1}0$2'
Antwort2
Dadurch werden alle „*.pdf“-Dateien im aktuellen Verzeichnis gefunden und umbenannt, deren Namen dem in der Frage beschriebenen Muster folgen. Sie erhalten denselben Namen, jedoch mit einer auf zwei Ziffern aufgefüllten Nummer:
#!/usr/bin/env bash
shopt -s nullglob
for f in *[[:space:]][0-9].pdf; do
int="$(basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1)"
name="$(basename "$f" | rev | cut -d ' ' -f2- | rev)"
padded_int="$(printf "%02d\n" "$int")"
echo mv "$f" "$(printf "%s %s.pdf" "$name" "$padded_int")"
done
Entfernen Sie es echo
, bevor mv
es tatsächlich ausgeführt wird mv
, aber führen Sie es zuerst so aus, wie es ist, um sicherzustellen, dass es das tut, was Sie möchten. Beispielverwendung mit dem oben genannten Skript, gespeichert unter pdf.sh
:
$ for i in {1..10}; do touch "C Block Scan copy $i.pdf"; done
$ ./pdf.sh
mv C Block Scan copy 1.pdf C Block Scan copy 01.pdf
mv C Block Scan copy 2.pdf C Block Scan copy 02.pdf
mv C Block Scan copy 3.pdf C Block Scan copy 03.pdf
mv C Block Scan copy 4.pdf C Block Scan copy 04.pdf
mv C Block Scan copy 5.pdf C Block Scan copy 05.pdf
mv C Block Scan copy 6.pdf C Block Scan copy 06.pdf
mv C Block Scan copy 7.pdf C Block Scan copy 07.pdf
mv C Block Scan copy 8.pdf C Block Scan copy 08.pdf
mv C Block Scan copy 9.pdf C Block Scan copy 09.pdf
Die erste Zeile:
#!/usr/bin/env bash
ist einsiebang. Außerdem verwende ich env
fürseine Eigenschaften.
Diese Linie
shopt -s nullglob
Sätzenullglob Shell-Option was auch auf der verlinkten Seite erklärt wird:
nullglob
If set, Bash allows filename patterns which match no files to
expand to a null string, rather than themselves.
Dies ist erforderlich, um den Start einer For-Schleife zu verhindern, wenn keine Dateien vorhanden sind, die den Musterkriterien entsprechen:
for f in *[[:space:]][0-9].pdf; do
*[[:space:]][0-9].pdf
ist ein Shell-Muster, das bedeutet, dass nach Dateien gesucht wird, deren Namen aus einer beliebigen Anzahl von Zeichen bestehen, gefolgt von einem Leerzeichen, gefolgt von einer einzelnen Ziffer und endend mit.pdf. In der Schleife $f
befindet sich der Name der verarbeiteten PDF-Datei.
Hier
int="$(basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1)"
wir gebrauchenBefehlsersetzung
um einer Variablen einen ganzzahligen Teil des angegebenen Dateinamens zuzuweisen. Sie können sehen, was basename
passiert, man basename
und die Pipeline im Terminal reproduzieren:
$ f='C Block Scan copy 1.pdf'
$ echo basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1
1
$ f='C Block Scan copy 5.pdf'
$ echo basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1
5
(Beachten Sie, dass $
hier einEingabeaufforderung
wird verwendet, um den Beginn einer neuen Zeile anzuzeigen, ist nicht Teil des Befehls).
In der nächsten Zeile
name="$(basename "$f" | rev | cut -d ' ' -f2- | rev)"
wir extrahieren den Namensteil der PDF-Datei, also alles vor der Nummer.
In der nächsten Zeile
padded_int="$(printf "%02d\n" "$int")"
Wir verwenden den integrierten Bash- printf
Befehl, um es aufzufüllen $int
und in einer Variable namens zu speichern padded_int
. In der letzten Zeile der Schleife
echo mv "$f" "$(printf "%s %s.pdf" "$name" "$padded_int")"
wir führen ( echo
natürlich ohne) die eigentliche Umbenennung mithilfe von printf
und Befehlsersetzung erneut aus. wird mit 2 Formatbezeichnern und 2 entsprechenden Argumenten printf
verwendet , ähnlich wie in C.%s
Die letzte Zeile
done
schließt den Kreis.
Antwort3
PE-Parametererweiterung verwenden. Nur mv
für externe Tools aus der bash
Shell.
#!/usr/bin/env bash
shopt -s nullglob
for f in *[[:space:]][0-9].pdf; do
n=${f##* } ##: Remain only 1.pdf, 2.pdf etc.
n=0${n%.*} ##: Remain only 1 , 2 etc. and pad 0 so it will be 01, 02 ..
echo mv -v "$f" "${f/[0-9]/"$n"}" ##: Replace all [0-9] with the value of "$n"
done
- SehenParametererweiterung