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.

jnhghy - Alexandru Jantea
quelle
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.

Gilles 'SO - hör auf böse zu sein'
quelle
5

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

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

Warwick
quelle
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 .

Marcelo Lacerda
quelle
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

Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
quelle
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
Sorav
quelle
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'