Ich möchte den Namen jedes Verzeichnisses unter einem Verzeichnis in Kleinbuchstaben schreiben. Mit welchen Befehlen kann ich das machen?
quelle
Ich möchte den Namen jedes Verzeichnisses unter einem Verzeichnis in Kleinbuchstaben schreiben. Mit welchen Befehlen kann ich das machen?
Alle Verzeichnisse auf einer Ebene oder rekursiv?
Auf einer Ebene:
autoload zmv
zmv -o-i -Q 'root/(*)(/)' 'root/${1:l}'
Rekursiv:
zmv -o-i -Q 'root/(**/)(*)(/)' 'root/$1${2:l}'
Erläuterungen: zmv
Benennt Dateien, die mit einem Muster übereinstimmen, gemäß dem angegebenen Ersetzungstext um. -o-i
Übergibt die -i
Option an jeden mv
Befehl unter der Haube (siehe unten). Im Ersetzungstext, $1
, $2
, usw., sind die aufeinanderfolgenden klammerten Gruppen in dem Muster. **
bezeichnet alle (Unter-) * Verzeichnisse rekursiv. Das Finale (/)
ist keine in Klammern gesetzte Gruppe, sondern ein Glob-Qualifikationsmerkmal, das bedeutet, dass nur Verzeichnisse abgeglichen werden. ${2:l}
konvertiert $2
in Kleinbuchstaben.
Auf einer Ebene:
for x in root/*/; do mv -i "$x" "$(printf %s "$x" | tr '[:upper:]' '[:lower:]')"; done
Das Finale /
schränkt den Abgleich auf Verzeichnisse ein und mv -i
fordert im Falle einer Kollision eine Bestätigung an. Entfernen Sie das -i
zu überschreibende Element im Falle einer Kollision und verwenden Sie yes n | for …
. Keine Aufforderung und keine kollidierende Umbenennung durchführen.
Rekursiv:
find root/* -depth -type d -exec sh -c '
t=${0%/*}/$(printf %s "${0##*/}" | tr "[:upper:]" "[:lower:]");
[ "$t" = "$0" ] || mv -i "$0" "$t"
' {} \;
Durch die Verwendung von wird -depth
sichergestellt, dass tief verschachtelte Verzeichnisse vor ihren Vorfahren verarbeitet werden. Die Namensverarbeitung beruht darauf, dass ein /
; Wenn Sie operieren im aktuellen Verzeichnis aufrufen möchten, verwenden Sie ./*
(Anpassung des Shell-Skripts zur Bewältigung von .
oder *
als Übung für den Leser).
Hier verwende ich das Perl-Umbenennungsskript, als das Debian und Ubuntu ausgeliefert werden /usr/bin/prename
(normalerweise auch verfügbar rename
). Auf einer Ebene:
rename 's!/([^/]*/?)$!\L/$1!' root/*/
Rekursiv mit bash ≥4 oder zsh:
shopt -s globstar # only in bash
rename 's!/([^/]*/?)$!\L/$1!' root/**/*/
Rekursiv portabel:
find root -depth -type d -exec rename -n 's!/([^/]*/?)$!\L/$1!' {} +
mv -i a a
Geben Sie "mv: a umbenennen in a / a: Ungültiges Argument" ein.-execdir
das ist genial: unix.stackexchange.com/questions/5412/... ich dann festgestellt , dass es etwas hatPATH
Wahnsinn und war traurig :-(Es gibt keinen einzigen Befehl, der das erledigt, aber Sie können so etwas tun:
Wenn es robust sein soll, sollten Sie berücksichtigen, dass es bereits zwei Verzeichnisse gibt, die sich nur für den Fall unterscheiden.
Als Einzeiler:
quelle
for file in * ; do if [ -d "$file" ] ; then dest="$(echo $file | sed y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/)" ; [ "$dest" != "$file" ] && mv "$file" "$dest" ; fi ; done
find -type d
, konnte es aber nicht ganz verstehenfor fd in */;
vermeiden, dass überprüft werden muss, ob es sich um ein Verzeichnis handelt, aber ich habe keine Ahnung, ob dieser Instinkt gut ist.tr
bereits einen Bereich,tr '[A-Z]' '[a-z]'
übersetzt also im Vorbeigehen[
nach[
und]
nach]
. Das ist nutzlos, aber harmlos; Ohne die Anführungszeichen würde die Shell jedoch die Klammern erweitern, wenn sich im aktuellen Verzeichnis eine Datei mit einem Namen in Großbuchstaben befindet.Ich habe dies als eine Ein-Linien-Herausforderung angesehen :) Stellen Sie zunächst einen Testfall auf:
Ich benutze
find
, um die Verzeichnisse mit Großbuchstaben zu erkennen und sie dann über in Kleinbuchstaben zu schreiben . Vermutlich ist das Verwenden etwas hackig, aber mein Kopf explodiert immer, wenn ich versuche, den Dingen direkt zu entkommen .sh -c 'mv {}
echo {} | tr [:upper:] [:lower:]
'sh -c
find
Seien Sie gewarnt: Diese Lösung prüft nicht, ob Downcasing zu Kollisionen führt!
quelle
mv -i
. Ein größeres Problem ist, dass Sie nicht die richtigen Anführungszeichen verwendet haben, sodass Ihr Befehl fehlschlägt, wenn\[*?
der Name Sonderzeichen (Leerzeichen oder ) enthält. Es hat keinen Sinn, esfind
sei denn, es ist rekursiv, und dann brauchen Siefind -depth
und-path
müssen es sein-name
. Siehe meine Antwort für Arbeitsbeispiele.mv -i
nachdem ich das geschrieben habe. Guter Punkt mit dem Zitieren ...find -execdir
| umbenennenDies wäre der beste Weg, es zu tun, wenn es nicht den relativen Pfadverrücktheit gäbe, da es Perl-Regex-Fu vermeidet, nur auf den Basisnamen zu reagieren:
-execdir
cd
s zuerst in das Verzeichnis, bevor es nur mit dem Basisnamen ausgeführt wird.Leider kann ich diesen
PATH
Hacking-Teil nicht loswerden undfind -execdir
weigere mich, irgendetwas zu tun, wenn Sie einen relativen Pfad inPATH
... haben: /ubuntu/621132/why-using-the-execdir-action- is-insecure-for-directory-which-is-the-path / 1109378 # 1109378quelle