it-swarm.com.de

Verwenden von sed zum Massenumbenennen von Dateien

Zielsetzung

Ändern Sie diese Dateinamen:

  • F00001-0708-RG-biasliuyda
  • F00001-0708-CS-akgdlaul
  • F00001-0708-VF-hioulgigl

zu diesen Dateinamen:

  • F0001-0708-RG-biasliuyda
  • F0001-0708-CS-akgdlaul
  • F0001-0708-VF-hioulgigl

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.

67

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.

125
Edward Anderson

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
36
ghostdog74

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.

16
Guy

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

14
Mike

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.

6
paxdiablo

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.

2
Pointy

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
0
Chris Po

Die Klammern erfassen bestimmte Zeichenfolgen, die von den umgekehrten Zahlen verwendet werden.

0
Ewan Todd
 ls F00001-0708-*|sed 's|^F0000\(.*\)|mv & F000\1|' | bash
0
ghostdog74

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.

0