Wie kann ich die Umbenennung verwenden, um alles rekursiv in Großbuchstaben umzubenennen?


11

Ich möchte alle Dateien und Ordner (Unterordner) rekursiv in Großbuchstaben umbenennen.

Ich habe einige Skripte gefunden, die es in Kleinbuchstaben machen, aber ich weiß nicht, wie ich sie ändern soll, damit es umgekehrt funktioniert (von unten nach oben).

Das Skript, das ich gefunden habe und das für Kleinbuchstaben funktioniert, aber ich wusste nicht, wie ich es ändern sollte, ist:

rename 'y/A-Z/a-z/' *

Es ist aus man rename.


Ohne etwas über den Umbenennungsbefehl zu wissen, vermute ich, dass rename 'y/a-z/A-Z/' *Sie das bekommen, was Sie wollen , wenn Sie es versuchen . Seien Sie vorsichtig, wo Sie es testen.
Warwick

es ist nicht rekursiv (weil das erste nicht war ...), aber es funktioniert. Ich kann nicht verstehen, warum ich das nicht selbst gelehrt habe :), dann!
jnhghy - Alexandru Jantea

Ich denke, angesichts der Qualität von Gilles 'Antwort wäre es gut, wenn Sie seine Antwort meiner vorziehen würden. Es ist viel vollständiger als meins und erklärt Ihre Optionen (und wie alles funktioniert). Vielen Dank.
Warwick

Antworten:


8

Beachten Sie, dass Sie das von Debian und Derivaten (Ubuntu, Mint,…) verteilte Perl-Skript verwendenrename . Andere Linux-Distributionen liefern einen völlig anderen und wesentlich weniger nützlichen Befehl namens rename.

y/A-Z/a-z/übersetzt jedes Zeichen im Bereich Adurch Zin das entsprechende Zeichen im Bereich adurch z, dh ASCII-Großbuchstaben in den entsprechenden Kleinbuchstaben. Verwenden Sie, um die entgegengesetzte Übersetzung durchzuführen y/a-z/A-Z/. Eine andere Möglichkeit, denselben Befehl zu schreiben, ist rename '$_ = uc($_)' *ucdie Funktion u pper c ase, und der renameBefehl benennt Dateien basierend auf der in die $_Variable vorgenommenen Umwandlung um .

rename '…' *benennt nur Dateien im aktuellen Verzeichnis um, da dies *übereinstimmt. Punktedateien (Dateien, deren Name mit beginnt .) werden ebenfalls übersprungen.

Wenn Sie Dateien im aktuellen Verzeichnis und in Unterverzeichnissen rekursiv umbenennen möchten, können Sie mit dem findBefehl das aktuelle Verzeichnis rekursiv durchlaufen. Hier gibt es eine Schwierigkeit: Wenn Sie aufrufen rename, werden sowohl das Verzeichnis als auch der Basisname umbenannt. Wenn Sie renameein Verzeichnis aufrufen, bevor Sie es erneut verwenden ( find -exec rename … {} \;), findwird dies verwirrt, da ein Verzeichnis gefunden wurde, dieses Verzeichnis jedoch nicht mehr vorhanden ist, wenn versucht wird, in dieses Verzeichnis abzusteigen. Sie können dies umgehen find, indem Sie anweisen , ein Verzeichnis zu durchlaufen, bevor Sie darauf reagieren. Am Ende versuchen Sie jedoch, es umzubenennen foo/bar, FOO/BARaber das Verzeichnis FOOexistiert nicht.

Eine einfache Möglichkeit, diese Schwierigkeit zu vermeiden, besteht darin, den Umbenennungsbefehl nur auf den Basisnamen des Pfads anzuwenden. Der reguläre Ausdruck ([^/]*\Z)entspricht dem letzten Teil des Pfads, der kein a enthält /.

find . -depth -exec rename 's!([^/]*\Z)!uc($1)!e' {} +

Die Shell zsh bietet bequemere Funktionen zum Umbenennen - noch kryptischer als Perl, aber knapper und oft einfacher zu komponieren.

Die Funktion zmvbenennt Dateien basierend auf Mustern um. Führen Sie es autoload -U zmveinmal aus, um es zu aktivieren (setzen Sie diese Zeile in Ihre .zshrc).

Im ersten Argument zu zmv(dem zu ersetzenden Muster) können Sie die leistungsstarken Platzhaltermuster von zsh verwenden . Im zweiten Argument zu zmv(dem Ersatztext) können Sie die Parametererweiterungsfunktionen einschließlich der Verlaufsmodifikatoren verwenden .

zmv -w '**/*' '$1$2:u'

Erläuterung:

  • -w - Automatische Zuweisung numerischer Variablen zu jedem Platzhaltermuster
  • **/*- Alle Dateien in Unterverzeichnissen rekursiv ( **/entspricht 0, 1 oder mehr Ebenen von Unterverzeichnissen)
  • $1 - die erste numerische Variable, die hier mit dem Verzeichnisteil jedes Pfads übereinstimmt
  • $2:u- die zweite numerische Variable, die hier mit dem :uBasisnamen jedes Pfads übereinstimmt, mit dem Modifikator, um den Wert in Großbuchstaben umzuwandeln

Als zusätzlichen Bonus werden die Einstellungen für das Gebietsschema der Umgebung berücksichtigt.

Wenn Sie sich bei einem von zmvIhnen geschriebenen Befehl nicht sicher sind , können Sie die -nOption übergeben, um zu drucken, was der Befehl tun würde, und nichts ändern. Überprüfen Sie die Ausgabe, und führen Sie den Befehl erneut aus, wenn er das tut, was Sie möchten, ohne -ntatsächlich zu handeln.


5

Gestohlen (mit einer geringfügigen Änderung) von Gilles Post hier

find <DIR> -depth -type d -exec rename -n 's!/([^/]*/?)$!\U/$1!' {} +


Dies wirkt nicht rekursiv.
Gilles 'SO - hör auf böse zu sein'

Wahr. Ich hätte die Frage richtig lesen sollen. Ich habe keinen Zugriff auf den Umbenennungsbefehl, aber ich glaube, dass dies rekursiv funktionieren wird -find <dir> -exec rename 'y/a-z/A-Z/' {} \;
Warwick

Es ist etwas komplizierter, weil Sie Verzeichnisse umbenennen, während findSie in sie zurückgreifen.
Gilles 'SO - hör auf böse zu sein'

@ Gilles - OK. Nach ein wenig Recherche scheint es, dass ich die Option -depth hinzufügen muss, um zu finden, dass die Verzeichnisnamen zuletzt behandelt werden. So find <dir> -depth -exec rename 'y/a-z/A-Z/' {} \;sollte die Umbenennung Verzeichnisse Problem umgehen. Richtig?
Warwick

Nein, das funktioniert immer noch nicht, da renameÄnderungen, z. B. foo/baran FOO/BARund FOOzu diesem Zeitpunkt nicht vorhanden sind.
Gilles 'SO - hör auf böse zu sein'

2

Ich möchte jeden, der noch mit dieser Antwort verbunden ist, auf die ausgezeichnete Antwort verweisen , die Guiles Quernot auf diese Frage gegeben hat, die nicht erforderlich ist find.

Der resultierende Befehl wäre:

shopt -s globstar
rename -n 'y/a-z/A-Z/' **

Aber bevor Sie loslegen, lesen Sie bitte die Antwort, die für Vorbehalte bezüglich alter Bash-Versionen verlinkt ist.

Schließlich, falls sich jemand fragt, was der y///Befehl bewirkt perl regex. Hier ist ein Link zur entsprechenden Dokumentation .


1

find -execdir| umbenennen

Dies wäre der beste Weg, wenn es nicht den relativen Pfadwahnsinn gäbe, da Perl Regex Fu nicht nur auf den Basisnamen reagiert:

PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
  find a -depth -execdir rename 's/(.*)/\U$1/' '{}' \;

-execdirZuerst cds in das Verzeichnis, bevor nur der Basisname ausgeführt wird.

Leider kann ich diesen PATHHacking-Teil nicht loswerden und find -execdirweigere mich, irgendetwas zu tun, wenn Sie einen relativen Pfad in PATH... haben: /ubuntu/621132/why-using-the-execdir-action- ist-unsicher-für-Verzeichnis-das-im-Pfad-ist / 1109378 # 1109378


0

Versuchen Sie dies, nachdem Sie in ein Verzeichnis verschoben haben, in dem Sie die Dateien umbenennen möchten:

for word in `ls -ltr |tail -n +2 |awk '{print $9}'`
do
  a=$(echo $word | tr '[a-z]' '[A-Z]')
  mv $word $a
  echo "Done Successfully"
done

Analysieren Sie nicht die Ausgabe von ls (und warum um alles in der Welt würden Sie ls -lnur laufen , um andere Spalten als den Namen abzuschneiden?) Und verwenden Sie doppelte Anführungszeichen um Variablensubstitutionen . Ihr Code ist zu komplex und enthält keine Dateinamen, die Leerzeichen und andere Sonderzeichen enthalten. Verwenden Sie findoder **/um in Unterverzeichnisse zurückzukehren, die Ausgabe von lsist nur für den menschlichen Verzehr.
Gilles 'SO - hör auf böse zu sein'
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.