Zielsetzung
Ändern Sie diese Dateinamen:
zu diesen Dateinamen:
Shell Code
Zu testen:
ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/'
Aufführen:
ls F00001-0708-*|sed 's/\(.\).\(.*\)/mv & \1\2/' | sh
Meine Frage
Ich verstehe den sed-Code nicht. Ich verstehe, was der Ersatz Befehl
$ sed 's/something/mv'
meint. Und ich verstehe reguläre Ausdrücke etwas. Aber ich verstehe nicht, was hier passiert:
\(.\).\(.*\)
oder hier:
& \1\2/
Ersteres sieht für mich einfach so aus, als würde es bedeuten: "ein einzelnes Zeichen , Gefolgt von einem einzelnen Zeichen, gefolgt von einer beliebigen Längensequenz eines - einzelnen Zeichens" - aber sicher ist noch mehr dabei. Soweit der letzte Teil:
& \1\2/
Ich habe keine Ahnung. Ich möchte diesen Code wirklich verstehen. Bitte hilf mir. Hier draußen, Jungs.
Zuerst sollte ich sagen, dass dies am einfachsten ist, die -Parstellennamen oder Umbenennungsbefehle zu verwenden.
Unter Ubuntu, OSX (Homebrew-Paket rename
, MacPorts-Paket p5-file-rename
) oder anderen Systemen mit Perl umbenennen (Vorname):
rename s/0000/000/ F0000*
oder auf Systemen mit umbenennen von util-linux-ng wie RHEL:
rename 0000 000 F0000*
Das ist viel verständlicher als der entsprechende sed-Befehl.
Für das Verständnis des sed-Befehls ist die sed-Manpage jedoch hilfreich. Wenn Sie den Befehl man sed ausführen und nach & suchen (mit dem Befehl/zum Suchen), Werden Sie feststellen, dass es ein Sonderzeichen in s/foo/bar/replace ist.
s/regexp/replacement/
Attempt to match regexp against the pattern space. If success‐
ful, replace that portion matched with replacement. The
replacement may contain the special character & to refer to that
portion of the pattern space which matched, and the special
escapes \1 through \9 to refer to the corresponding matching
sub-expressions in the regexp.
Daher stimmt \(.\)
mit dem ersten Zeichen überein, auf das mit \1
..__ verwiesen werden kann. .
stimmt mit dem nächsten Zeichen überein, das immer 0 ..__ ist, und \(.*\)
stimmt mit dem Rest des Dateinamens überein, auf das mit \2
verwiesen werden kann.
Die Ersetzungszeichenfolge setzt alles zusammen aus &
(dem ursprünglichen Dateinamen) und \1\2
, die alle Teile des Dateinamens sind, mit Ausnahme des 2. Zeichens, das eine 0 war.
Dies ist eine ziemlich kryptische Methode, IMHO. Wenn aus irgendeinem Grund der Umbenennungsbefehl nicht verfügbar war und Sie die Umbenennung mithilfe von Sed ausführen möchten (oder Sie haben vielleicht etwas zu komplexes .__ für die Umbenennung?), Wäre dies in Ihrer Regex expliziter machen es viel besser lesbar. Vielleicht so etwas wie:
ls F00001-0708-*|sed 's/F0000\(.*\)/mv & F000\1/' | sh
Wenn Sie sehen können, was sich in der S/Suche/Ersetzung/tatsächlich ändert, ist dies viel besser lesbar. Es wird auch nicht zulassen, dass Zeichen aus Ihrem Dateinamen saugt, wenn Sie es zweimal aus Versehen zweimal ausführen.
sie hatten Ihre Sed-Erklärung, jetzt können Sie nur die Shell verwenden, keine externen Befehle
for file in F0000*
do
echo mv "$file" "${file/#F0000/F000}"
# ${file/#F0000/F000} means replace the pattern that starts at beginning of string
done
Ich habe vor einigen Jahren einen kleinen Beitrag mit Beispielen zur Stapelumbenennung mit sed
geschrieben:
http://www.guyrutenberg.com/2009/01/12/batch-renaming-using-sed/
Zum Beispiel:
for i in *; do
mv "$i" "`echo $i | sed "s/regex/replace_text/"`";
done
Wenn der reguläre Ausdruck Gruppen enthält (z. B. \(subregex\
), können Sie diese im Ersetzungstext als \1\
, \2
usw. verwenden.
Der einfachste Weg wäre:
for i in F00001*; do mv "$i" "${i/F00001/F0001}"; done
oder tragbar
for i in F00001*; do mv "$i" "F0001${i#F00001}"; done
Dies ersetzt das F00001
-Präfix in den Dateinamen durch F0001
. Credits an Mahesh hier: http://www.debian-administration.org/articles/150
Der Befehl sed
s/\(.\).\(.*\)/mv & \1\2/
bedeutet zu ersetzen:
\(.\).\(.*\)
mit:
mv & \1\2
genau wie ein normaler sed
Befehl. Die Klammern &
und \n
ändern dies jedoch etwas.
Die Suchzeichenfolge entspricht (und speichert als Muster 1) das einzelne Zeichen am Anfang, gefolgt von einem einzelnen Zeichen, gefolgt vom Rest der Zeichenfolge (als Muster 2 gespeichert).
In der Ersetzungszeichenfolge können Sie auf diese übereinstimmenden Muster verweisen, um sie als Teil der Ersetzung zu verwenden. Sie können sich auch auf den gesamten übereinstimmenden Teil als &
beziehen.
Der sed
-Befehl erstellt also einen mv
-Befehl, der auf der Originaldatei (für die Quelle) und den Zeichen 1 und 3 aufwärts basiert, wodurch Zeichen 2 (für das Ziel) entfernt wird. Sie erhalten eine Reihe von Zeilen mit folgendem Format:
mv F00001-0708-RG-biasliuyda F0001-0708-RG-biasliuyda
mv abcdef acdef
und so weiter.
Das Backslash-Paren-Material bedeutet: "Wenn Sie das Muster anpassen, behalten Sie das Zeug, das hier passt." Später können Sie diese ersetzten Fragmente auf der Ersetzungstextseite mit "\ 1" (erster Klammerblock), "\ 2" (zweiter Block) usw. zurückgeben.
Folgendes würde ich tun:
for file in *.[Jj][Pp][Gg] ;do
echo mv -vi \"$file\" `jhead $file|
grep Date|
cut -b 16-|
sed -e 's/:/-/g' -e 's/ /_/g' -e 's/$/.jpg/g'` ;
done
Wenn dies in Ordnung ist, fügen Sie am Ende | sh
hinzu. So:
for file in *.[Jj][Pp][Gg] ;do
echo mv -vi \"$file\" `jhead $file|
grep Date|
cut -b 16-|
sed -e 's/:/-/g' -e 's/ /_/g' -e 's/$/.jpg/g'` ;
done | sh
Die Klammern erfassen bestimmte Zeichenfolgen, die von den umgekehrten Zahlen verwendet werden.
ls F00001-0708-*|sed 's|^F0000\(.*\)|mv & F000\1|' | bash
Wenn Sie wirklich nur das zweite Zeichen entfernen, können Sie Folgendes tun:
s/.//2
ihr Befehl erstellt jedoch einen mv
-Befehl und leitet ihn zur Ausführung an die Shell weiter.
Dies ist nicht lesbarer als Ihre Version:
find -type f | sed -n 'h;s/.//4;x;s/^/mv /;G;s/\n/ /g;p' | sh
Das vierte Zeichen wird entfernt, da find
jedem Dateinamen "./" voranstellt.