Ich versuche, alle Dateien, die mit einem „m“ beginnen, so umzubenennen, dass sie denselben Namen haben, jedoch das erste Zeichen (oder in diesem Fall „m“) entfernt wird.
Meine Strategie ist:
- Alle Dateien auflisten, mit
ls
- Filtern Sie nach den gewünschten, mit
egrep
- Generieren Sie die Zeichenfolge, die ich nicht möchte, neben der Zeichenfolge, die ich möchte, getrennt durch ein Leerzeichen,
awk
beispielsweise mitmfoo foo
- Einspeisen
xargs
inmv mfoo foo
Einige Fragen:
- Ist das eine gute Strategie?
- Was ist besser?
Ich stecke bei Schritt 3 fest. Unten sehen Sie, wie ich das Problem angegangen bin.
Ich arbeite in folgendem Verzeichnis:
$ find .
.
./cat
./mbar
./mbaz
./mfoo
Ich kann schnell 1-2 bekommen:
$ ls | egrep '^m'
mbar
mbaz
mfoo
Schritt 3 ist schwieriger. Ich gsub
habe früher die zweite gewünschte Zeichenfolge generiert, bin mir aber nicht sicher, wie ich sie „mit dem Originalwert, getrennt durch ein Leerzeichen, zusammenfügen“ kann:
$ ls | egrep '^m' | awk '{ gsub(/^./, ""); print }'
bar
baz
foo
Schritt 4 ergibt für mich Sinn, obwohl ich nicht sicher bin, wie ich Schritt 3 abschließen soll, also kann ich ihn noch nicht abschließen. Unten ist ein Beispiel, wie es meiner Meinung nach funktionieren sollte:
$ echo mfoo foo | xargs mv
$ find .
.
./cat
./foo
./mbar
./mbaz
Ich glaube, ich bin nah dran. Ich muss nur noch herausfinden, wie ich den alten Wert speichere und ihn neben dem gsubed-Wert ausdrucke. Ich habe das folgende kleine Beispiel ausprobiert, aber es funktioniert nicht:
$ echo mfoo | awk '
pipe quote> { old = $0 }
pipe quote> { new = gsub(/^./, "") }
pipe quote> { print $old " " $new }'
awk: illegal field $(mfoo), name "old"
input record number 1, file
source line number 4
- Wie kann ich eine Ersetzung vornehmen,
$0
aber den alten Wert beibehalten? - Warum erhalte ich diesen Fehler?
Antwort1
Dies sollte den gesamten Vorgang abwickeln:
for file in m*; do mv "${file}" "${file#m}"; done
Bevor Sie das ausführen, überprüfen Sie die Dinge zunächst mit
for file in m*; do echo mv "${file}" "${file#m}"; done
Dabei wird der m*
Glob für die Schritte 1 und 2 verwendet, dann ${file#m}
(wodurch „m“ am Anfang entfernt wird ${file}
) für Schritt 3 und schließlich eine Schleife für Schritt 4.
Um Ihre AWK-Frage zu beantworten, könnten Sie folgendermaßen vorgehen:
echo mfoo | awk '{ print $0, substr($0, 2) }'
AWK-Variablen verwenden nicht $
, das ist nur für Felder; daher kommt Ihr Fehler: AWK versteht $old
als „den Wert des Felds, nummeriert nach dem Wert von old
“. Es ist auch leichter zu lesen, wenn Sie Ihre Befehle in einem einzigen Block platzieren (vorausgesetzt, sie haben das gleiche Muster). Das Korrigieren Ihres Skripts ergibt
echo mfoo | awk '{ old = $0; gsub(/^./, ""); print old, $0 }'
Antwort2
ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); $0 = x " " $0 }1' | xargs -l -t mv
Posix-lyDie Implementierung erfolgt über die -L
Option xargs
:
ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); $0 = x " " $0 }1' | xargs -L 1 -t mv
ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); print x, $0 }' | xargs -L 1 -t mv
Basierend woraufich antworteteAls Antwort auf Ihre frühere Frage zu xargs
können wir das Gelernte in diesem Beispiel gut nutzen.
Ich habe Ihren awk
Code leicht modifiziert: Er behält die ursprüngliche Zeile ( $0
) bei, da die gsub
Funktion sie überschreiben wird. Dann fügen wir das Alte und das Neue zusammen, um die Zeile zu erhalten, die wir senden möchten, xargs
die dann mit den richtigen Argumenten aufgerufen wird mv
, um die Umbenennung durchzuführen.
Antwort3
Eine bessere Strategie ist die Verwendung des rename
Befehls.
Beachten Sie, dass die genaue Syntax dieser Befehle distributionsspezifisch ist. Konsultieren Sie die man
Seite Ihrer jeweiligen Distributionsversion. Unter Ubuntu beispielsweise, das eine Perl-Implementierung von hat rename
, können Sie einen regulären Ausdruck verwenden:
rename -nono 's/^m//' m*
Hinweis: Entfernen Sie das -nono
Flag, um die Umbenennung tatsächlich durchzuführen.