Wie benenne ich alle Ordner und Dateien unter Linux in Kleinbuchstaben um?

179

Ich muss einen vollständigen Ordnerbaum rekursiv umbenennen, damit nirgendwo Großbuchstaben angezeigt werden (es ist C ++ - Quellcode, aber das sollte keine Rolle spielen).

Bonuspunkte für das Ignorieren von CVS- und Subversion-Versionskontrolldateien / -ordnern. Der bevorzugte Weg wäre ein Shell-Skript, da eine Shell auf jeder Linux-Box verfügbar sein sollte.

Es gab einige gültige Argumente zu Details der Umbenennung von Dateien.

  1. Ich denke, Dateien mit denselben Kleinbuchstaben sollten überschrieben werden. Es ist das Problem des Benutzers. Beim Auschecken in einem Dateisystem, bei dem die Groß- und Kleinschreibung ignoriert wird, wird auch das erste mit dem letzteren überschrieben.

  2. Ich würde AZ-Zeichen betrachten und sie in az umwandeln, alles andere erfordert nur Probleme (zumindest mit dem Quellcode).

  3. Das Skript wird benötigt, um einen Build auf einem Linux-System auszuführen. Daher sollten Änderungen an CVS- oder Subversion-Versionskontrolldateien weggelassen werden. Immerhin ist es nur eine Rubbelkasse. Vielleicht ist ein "Export" angemessener.

vividos
quelle
Die zuvor veröffentlichten Informationen funktionieren sofort oder mit einigen Anpassungen für einfache Fälle. Es gibt jedoch einige Situationen, die Sie berücksichtigen sollten, bevor Sie die Stapelumbenennung ausführen: 1. Was sollte passieren, wenn Sie zwei oder mehr Namen bei haben? die gleiche Ebene in der Pfadhierarchie , die nur von Fall zu unterscheiden, wie zum Beispiel ABCdef, abcDEFund aBcDeF? Sollte das Umbenennungsskript abbrechen oder nur warnen und fortfahren? 2. Wie definieren Sie Kleinbuchstaben für Nicht-US-ASCII-Namen? Wenn solche Namen vorhanden sein könnten, sollte zuerst eine Überprüfung und ein Ausschluss durchgeführt werden? 3. Wenn Sie eine Umbenennungsoperation ausführen
Mihai Limbășan

Antworten:

179

Eine kurze Version mit dem "rename"Befehl:

find my_root_dir -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;

Dies vermeidet Probleme beim Umbenennen von Verzeichnissen vor Dateien und beim Versuch, Dateien in nicht vorhandene Verzeichnisse (z . B. "A/A"in "a/a") zu verschieben.

Oder eine ausführlichere Version ohne Verwendung "rename".

for SRC in `find my_root_dir -depth`
do
    DST=`dirname "${SRC}"`/`basename "${SRC}" | tr '[A-Z]' '[a-z]'`
    if [ "${SRC}" != "${DST}" ]
    then
        [ ! -e "${DST}" ] && mv -T "${SRC}" "${DST}" || echo "${SRC} was not renamed"
    fi
done

PS

Letzteres ermöglicht mehr Flexibilität mit dem Befehl move (z. B. "svn mv").

Alex B.
quelle
36
Die Umbenennung kann auch auf diese Weise erfolgen: 'y / AZ / az /' *
Tzury Bar Yochay
3
Beachten Sie, dass beide Versionen in einem Dateisystem ohne Berücksichtigung der Groß- und Kleinschreibung nicht funktionieren. In meinem Fall habe ich die thengeschlossene Zeile durch ersetzt (mv "${SRC}" "${DST}.renametmp" && mv "${DST}.renametmp" "${DST}") || echo "${SRC} was not renamed".
Lloeki
6
Der zweite Ansatz funktionierte bei Dateien mit Leerzeichen (Kontext: Linux, Bash) nicht richtig.
Dim
4
Bei Verwendung der letzten Version des Umbenennens ist kein regulärer Ausdruck erforderlich. Der vollständige Befehl wird find my_root_dir -depth -exec rename -c {} \;. Fügen Sie -f hinzu, um umzubenennen, wenn Sie sich in einem Dateisystem befinden, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird (z. B. Mac)
Javache
Der zweite arbeitete für mich unter Solaris, indem er den -Taus dem mvBefehl entfernte.
Ham
261

Kleiner noch mag ich ganz:

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

Bei Dateisystemen ohne Berücksichtigung der Groß- und Kleinschreibung, z. B. HFS + von OS X , sollten Sie das folgende -fFlag hinzufügen :

rename -f 'y/A-Z/a-z/' *
Tristanbailey
quelle
3
linux.icydog.net/rename.php :The renaming utility that comes by default with Ubuntu is a Perl program sometimes called prename
sleepsort
1
Danke, ich habe es so benutzt $ find | xargs benennen 'y / AZ / az /' * um
Rashi
5
Dies setzt voraus, dass Sie Perls umbenennen, was nicht immer der Fall ist. zB bei meinem Debian ist die Umbenennung völlig anders
Krzysztof Krasoń
10
Auf Arch wird das Programm aufgerufen perl-rename(und von einem gleichnamigen Paket bereitgestellt)
jaymmer - Reinstate Monica
3
Dies beantwortet das gegebene Problem nicht, da "Umbenennen" nicht rekursiv ist.
Cybolic
89
for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
Swaroop CH
quelle
Bitte machen Sie ein "mkdir -p A / B / C", bevor Sie Ihr Skript ausführen.
tzot
2
"find" sollte durch einen beliebigen Befehl ersetzt werden, mit dem Sie eine Liste der Dateien abrufen, die Sie umbenennen möchten. Zum Beispiel "ls *. {C, CPP, H}".
JPaget
2
Funktioniert nicht unter OS X, druckt nur die Nutzungsinformationen für find. find .scheint dies zu beheben.
Emlai
3
Die "konsolidierte" Version, aus allen Kommentaren (Antwort kann nicht mehr bearbeitet werden):for f in `find .`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
Romaricdrigon
1
Kann mir jemand erklären, warum das überhaupt funktionieren sollte? Wenn es ./FOO und ./FOO/BAR findet, benennt es zuerst ./FOO in ./foo um, danach kann es ./FOO/BAR nicht mehr finden. Wenn Sie unten meine eigene Antwort eingeben, sollte dies behoben sein.
Oisyn
79

Versuchen Sie einfach Folgendes, wenn Sie sich nicht um Effizienz kümmern müssen.

zip -r foo.zip foo/*
unzip -LL foo.zip
Ginhing
quelle
13
Wow, das ist ein ziemlich ineffizienter Weg.
Artjom B.
28
Angenommen, die Recheneffizienz ist normalerweise KEIN Problem, wenn Sie Dateien in einem Verzeichnis umbenennen müssen ... Ich denke, dies ist wahrscheinlich die kreativste und einfachste Lösung für diesen Thread. Wirklich etwas, das so trivial ist, sollte nicht so kompliziert sein, wie die akzeptierten Antworten zeigen, und diese Problemumgehung ist weitaus verhältnismäßiger für die Menge an Gedanken, die ich in eine Operation wie diese investieren möchte. +1000
Peter M. Elias
27
Sie können es mit dem -0Schalter (das ist 'Null', keine Komprimierung) beschleunigen zip -0 -r foo.zip foo/.
Johnny Baloney
3
Ich musste über 50'000 Dateinamen in verschiedenen Verzeichnisstrukturen ändern. Die ursprünglich akzeptierte Antwort erledigte kaum 10% der Arbeit in 2 Minuten, wo dies mit der -0Komprimierung fast augenblicklich war!
Peon
2
Dies ist nicht nur ineffizient. Dieser ist einfach unmöglich, wenn nicht genügend freier Speicherplatz für ein temporäres Archiv vorhanden ist.
Victor Yarema
18

Mann, ihr Jungs / Mädels mag es, Dinge zu komplizieren ... Benutzen:

rename 'y/A-Z/a-z/' *
Stephen
quelle
2
Dies funktioniert nicht, es heißt, dass die Datei mit dem Namen in Kleinbuchstaben bereits vorhanden ist.
Kirhgoff
@ kirhgoff Ich habe gesehen, dass dies bei NFS-Reittieren passiert - folgen Sie den Anweisungen hier .
Joeb
Wie können wir in einem Dateisystem mit Groß- und Kleinschreibung umbenennen? rename 'y/a-z/A-Z/' /tmp/*.jpg-> Can't rename /tmp/*.jpg /TMP/*.JPG: No such file or directory, dh versuchen Sie, den gesamten Pfad anstelle nur der Datei umzubenennen.
Pablo A
14

Die meisten der oben genannten Antworten sind gefährlich, da sie sich nicht mit Namen befassen, die ungerade Zeichen enthalten. Ihre sicherste Wette für diese Art von Dingen ist die Verwendung findder -print0Option, mit der Dateinamen mit ASCII NUL anstelle von \ n beendet werden.

Hier ist ein Skript, das nur Dateien und keine Verzeichnisnamen ändert, um nicht zu verwirren find:

find .  -type f -print0 | xargs -0n 1 bash -c \
's=$(dirname "$0")/$(basename "$0");
d=$(dirname "$0")/$(basename "$0"|tr "[A-Z]" "[a-z]"); mv -f "$s" "$d"'

Ich habe es getestet und es funktioniert mit Dateinamen, die Leerzeichen, Anführungszeichen aller Art usw. enthalten. Dies ist wichtig, da Sie als Root eines dieser anderen Skripte in einem Baum ausführen, der die von erstellte Datei enthält

touch \;\ echo\ hacker::0:0:hacker:\$\'\057\'root:\$\'\057\'bin\$\'\057\'bash

... Rate mal ...

niXar
quelle
Es wäre einfacher zu verwenden renameals mv.
Victor Yarema
14

Dies funktioniert, wenn Sie den Umbenennungsbefehl bereits haben oder eingerichtet haben (z. B. durch Brew-Installation auf dem Mac):

rename --lower-case --force somedir/*
Alemol
quelle
9
... wenn Sie zuerst umbenennen, zB durchbrew install rename
pduersteler
3
benenne 'y / AZ / az /' * um
Stephen
4
--lower-case? Das ist zumindest unter Arch Linux leider nicht der Fall.
3
renameist keine eingebaute Bash. Es ist ein externes Dienstprogramm und die Syntax hängt von der installierten Version ab. Diese Antwort reicht als tragbare Lösung "für alle Unix-basierten Betriebssysteme" nicht aus.
Corey Goldberg
2
Gerade überprüft, hat der renameBefehl, der in der neuesten Version von Fedora (28) enthalten ist, über das util-linux-2.31Paket keine --lower-caseOption.
NiXar
11

Dies funktioniert unter CentOS / Red Hat Linux oder anderen Distributionen ohne das renamePerl-Skript:

for i in $( ls | grep [A-Z] ); do mv -i "$i" "`echo $i | tr 'A-Z' 'a-z'`"; done

Quelle: Benennen Sie alle Dateinamen von Groß- in Kleinbuchstaben um

(In einigen Distributionen stammt der Standardbefehl renamevon util-linux, und das ist ein anderes, inkompatibles Tool.)

Pere
quelle
Dies funktioniert nur in einem einzigen Verzeichnis, nicht rekursiv
Bram
Coool .. Funktioniert gut
Manikandan Ram
6

Der einfachste Ansatz, den ich unter Mac OS X gefunden habe, war die Verwendung des Umbenennungspakets von http://plasmasturm.org/code/rename/ :

brew install rename
rename --force --lower-case --nows *

--force Rename auch dann, wenn bereits eine Datei mit dem Zielnamen vorhanden ist.

--lower-case Konvertiert Dateinamen in Kleinbuchstaben.

--nows Ersetzen Sie alle Leerzeichenfolgen im Dateinamen durch einzelne Unterstriche.

Kim T.
quelle
5

Hier ist meine suboptimale Lösung mit einem Bash-Shell-Skript:

#!/bin/bash
# First, rename all folders
for f in `find . -depth ! -name CVS -type d`; do
   g=`dirname "$f"`/`basename "$f" | tr '[A-Z]' '[a-z]'`
   if [ "xxx$f" != "xxx$g" ]; then
      echo "Renaming folder $f"
      mv -f "$f" "$g"
   fi
done

# Now, rename all files
for f in `find . ! -type d`; do
   g=`dirname "$f"`/`basename "$f" | tr '[A-Z]' '[a-z]'`
   if [ "xxx$f" != "xxx$g" ]; then
      echo "Renaming file $f"
      mv -f "$f" "$g"
   fi
done

Ordner werden alle korrekt umbenannt, und mv keine Fragen, wenn die Berechtigungen nicht übereinstimmen, und CVS-Ordner werden nicht umbenannt (CVS-Steuerdateien in diesem Ordner werden leider immer noch umbenannt).

Da "find -depth" und "find | sort -r" beide die Ordnerliste in einer verwendbaren Reihenfolge zum Umbenennen zurückgeben, habe ich es vorgezogen, "-depth" zum Durchsuchen von Ordnern zu verwenden.

vividos
quelle
Ihr erster Fund funktioniert nicht. Versuchen Sie "mkdir -p A / B / C" und führen Sie dann Ihr Skript aus.
Zot
4

In der ursprünglichen Frage wurde das Ignorieren von SVN- und CVS-Verzeichnissen gestellt. Dies kann durch Hinzufügen von -prune zum Befehl find erfolgen. ZB CVS ignorieren:

find . -name CVS -prune -o -exec mv '{}' `echo {} | tr '[A-Z]' '[a-z]'` \; -print

[Bearbeiten] Ich habe dies ausprobiert und das Einbetten der Kleinbuchstabenübersetzung in den Fund hat aus Gründen, die ich nicht wirklich verstehe, nicht funktioniert. Ändern Sie dies also in:

$> cat > tolower
#!/bin/bash
mv $1 `echo $1 | tr '[:upper:]' '[:lower:]'`
^D
$> chmod u+x tolower 
$> find . -name CVS -prune -o -exec tolower '{}'  \;

Ian

Ian Dickinson
quelle
4

Verwenden des Dateinamen-Fixers von Larry Wall:

$op = shift or die $help;
chomp(@ARGV = <STDIN>) unless @ARGV;
for (@ARGV) {
    $was = $_;
    eval $op;
    die $@ if $@;
    rename($was,$_) unless $was eq $_;
}

Es ist so einfach wie

find | fix 'tr/A-Z/a-z/'

(wo fixist natürlich das obige Skript)

agnul
quelle
3

Dies ist ein kleines Shell-Skript, das das tut, was Sie angefordert haben:

root_directory="${1?-please specify parent directory}"
do_it () {
    awk '{ lc= tolower($0); if (lc != $0) print "mv \""  $0 "\" \"" lc "\"" }' | sh
}
# first the folders
find "$root_directory" -depth -type d | do_it
find "$root_directory" ! -type d | do_it

Beachten Sie die Aktion -tiefe im ersten Fund.

tzot
quelle
1
Das einzige, was auf einem Mac aus dem ganzen Thread funktioniert hat. Tausend Dank!
YemSalat
2

Nicht tragbar, nur Zsh, aber ziemlich prägnant.

Stellen Sie zunächst sicher, dass zmvgeladen ist.

autoload -U zmv

Stellen Sie außerdem sicher, dass Folgendes aktiviert extendedglobist:

setopt extendedglob

Dann benutze:

zmv '(**/)(*)~CVS~**/CVS' '${1}${(L)2}'

Rekursiv Kleinbuchstaben von Dateien und Verzeichnissen, bei denen der Name nicht CVS ist .

benjwadams
quelle
2
for f in `find -depth`; do mv ${f} ${f,,} ; done

find -depthdruckt jede Datei und jedes Verzeichnis, wobei der Inhalt eines Verzeichnisses vor dem Verzeichnis selbst gedruckt wird. ${f,,}Kleinschreibung des Dateinamens.

Chris Schierkolk
quelle
Dies funktioniert nicht: Es benennt ein Verzeichnis um, bevor es den Inhalt bearbeitet, sodass der spätere Versuch des Inhalts fehlschlägt.
Beschneiden Sie
Das Hinzufügen -depthbehebt das! Dies ist eine wirklich schnelle Lösung, aber natürlich ohne die -print0Option zu finden, ist es nicht die zuverlässigste
jpaugh
@jpaugh Nein, tut es nicht. Es wird versucht, ./FOO/BAR in ./foo/bar umzubenennen, aber ./foo ist zu diesem Zeitpunkt noch nicht vorhanden.
Oisyn
2

Unter MacOS

Installieren Sie das renamePaket,

brew install rename

Verwenden,

find . -iname "*.py" -type f | xargs -I% rename -c -f  "%"                       

Dieser Befehl findet alle Dateien mit einer *.pyErweiterung und konvertiert die Dateinamen in Kleinbuchstaben.

`f` - forces a rename

Beispielsweise,

$ find . -iname "*.py" -type f
./sample/Sample_File.py
./sample_file.py
$ find . -iname "*.py" -type f | xargs -I% rename -c -f  "%"
$ find . -iname "*.py" -type f
./sample/sample_file.py
./sample_file.py
Akilesh Raj
quelle
Warum haben Sie hier die -IOption verwendet xargs?
Victor Yarema
Die - IFlagge ist nicht obligatorisch. Es wird verwendet, wenn wir mehrere Befehle mit ausführen xargs. Hier ist ein Beispiel für die Verwendung mehrerer Befehle mit xargs cat foo.txt | xargs -I % sh -c 'echo %; mkdir %' Sie können ohne -Ilike find . -iname "*.py" -type f | xargs -I% rename -c -f "%"
ausführen
2

Verwendung typeset :

typeset -l new        # Always lowercase
find $topPoint |      # Not using xargs to make this more readable
  while read old
  do new="$old"       # $new is a lowercase version of $old
     mv "$old" "$new" # Quotes for those annoying embedded spaces
  done

Unter Windows können Emulationen wie Git Bash fehlschlagen, da Windows unter der Haube nicht zwischen Groß- und Kleinschreibung unterscheidet. mvFügen Sie für diese einen Schritt, bei dem es sich um die Datei handelt, zuerst einem anderen Namen hinzu, z. B. "$ old.tmp", und dann einem $new.

Paul Hodges
quelle
1

Langwierig, aber "funktioniert ohne Überraschungen und ohne Installationen"

Dieses Skript verarbeitet Dateinamen mit Leerzeichen, Anführungszeichen, anderen ungewöhnlichen Zeichen und Unicode. Es funktioniert in Dateisystemen ohne Berücksichtigung der Groß- und Kleinschreibung und in den meisten Unix-y-Umgebungen , in denen bash und awk installiert sind (dh fast alle). Es werden auch eventuelle Kollisionen gemeldet (wobei der Dateiname in Großbuchstaben belassen wird) und natürlich sowohl Dateien als auch Verzeichnisse umbenannt und rekursiv ausgeführt. Schließlich ist es sehr anpassungsfähig: Sie können den Befehl find optimieren, um auf die gewünschten Dateien / Verzeichnisse abzuzielen, und Sie können awk optimieren, um andere Namensmanipulationen durchzuführen. Beachten Sie, dass mit "behandelt Unicode" meine, dass es tatsächlich ihre Groß- / Kleinschreibung konvertiert (ignorieren Sie sie nicht wie Antworten, die verwendet werden tr).

# adapt the following command _IF_ you want to deal with specific files/dirs
find . -depth -mindepth 1 -exec bash -c '
  for file do
    # adapt the awk command if you wish to rename to something other than lowercase
    newname=$(dirname "$file")/$(basename "$file" | awk "{print tolower(\$0)}")
    if [ "$file" != "$newname" ] ; then
        # the extra step with the temp filename is for case-insensitive filesystems
        if [ ! -e "$newname" ] && [ ! -e "$newname.lcrnm.tmp" ] ; then
           mv -T "$file" "$newname.lcrnm.tmp" && mv -T "$newname.lcrnm.tmp" "$newname" 
        else
           echo "ERROR: Name already exists: $newname"
        fi
    fi    
  done
' sh {} +

Verweise

Mein Skript basiert auf diesen hervorragenden Antworten:

/unix/9496/looping-through-files-with-spaces-in-the-names

Wie konvertiere ich eine Zeichenfolge in Bash in Kleinbuchstaben?

ndemou
quelle
1

Dies funktioniert auch unter MacOS:

ruby -e "Dir['*'].each { |p| File.rename(p, p.downcase) }"
Chris
quelle
Dies ist besonders schön, da Ruby mit macOS ausgeliefert wird.
jxmorris12
1

Ich musste dies bei einem Cygwin-Setup unter Windows 7 tun und stellte fest, dass ich Syntaxfehler mit den oben genannten Vorschlägen hatte (obwohl ich möglicherweise eine funktionierende Option verpasst habe). Diese Lösung direkt aus den Ubuntu-Foren hat jedoch aus der Dose heraus funktioniert :-)

ls | while read upName; do loName=`echo "${upName}" | tr '[:upper:]' '[:lower:]'`; mv "$upName" "$loName"; done

(NB: Ich hatte zuvor Leerzeichen durch Unterstriche ersetzt, indem ich:

for f in *\ *; do mv "$f" "${f// /_}"; done

)

Jacanterbury
quelle
1

In OS X wird der mv -fFehler "Gleiche Datei" angezeigt, daher benenne ich ihn zweimal um:

for i in `find . -name "*" -type f |grep -e "[A-Z]"`; do j=`echo $i | tr '[A-Z]' '[a-z]' | sed s/\-1$//`; mv $i $i-1; mv $i-1 $j; done
Jonghee Park
quelle
1

In dieser Situation würde ich nach Python greifen, um zu vermeiden, dass Pfade ohne Leerzeichen oder Schrägstriche optimistisch angenommen werden. Ich habe auch festgestellt, dass python2in der Regel an mehr Orten als installiert werden rename.

#!/usr/bin/env python2
import sys, os

def rename_dir(directory):
  print('DEBUG: rename('+directory+')')

  # Rename current directory if needed
  os.rename(directory, directory.lower())
  directory = directory.lower()

  # Rename children
  for fn in os.listdir(directory):
    path = os.path.join(directory, fn)
    os.rename(path, path.lower())
    path = path.lower()

    # Rename children within, if this child is a directory
    if os.path.isdir(path):
        rename_dir(path)

# Run program, using the first argument passed to this Python script as the name of the folder
rename_dir(sys.argv[1])
John Foley
quelle
Sprechen Sie darüber, es kompliziert zu machen ... tun Sie es einfach ... benennen Sie 'y / AZ / az /' * um
Stephen
1
@Stephen, das setzt voraus, dass Sie Administratorzugriff haben, um die Umbenennung zu installieren. Ich muss häufig Daten auf Systemen mischen, auf denen ich keine andere Software installieren kann. In Ubuntus wird dies nur installiert, wenn Perl vorhanden ist.
John Foley
1

Wenn Sie Arch Linux verwenden , können Sie ein renamePaket installieren AUR, das den renamexmBefehl als /usr/bin/renamexmausführbare Datei und eine Handbuchseite dazu bereitstellt .

Es ist ein wirklich mächtiges Werkzeug, um Dateien und Verzeichnisse schnell umzubenennen.

In Kleinbuchstaben konvertieren

rename -l Developers.mp3 # or --lowcase

In UPPER-Fall konvertieren

rename -u developers.mp3 # or --upcase, long option

Andere Optionen

-R --recursive # directory and its children

-t --test # Dry run, output but don't rename

-o --owner # Change file owner as well to user specified

-v --verbose # Output what file is renamed and its new name

-s/str/str2 # Substitute string on pattern

--yes # Confirm all actions

Sie können die Beispieldatei Developers.mp3 bei Bedarf von hier abrufen;)

Peter Mortensen
quelle
1
Das Umbenennen von brewunter macOS hat -ldazu geführt, dass ein Symlink erstellt und -cin Kleinbuchstaben konvertiert werden muss.
Rien333
0
( find YOURDIR -type d | sort -r;
  find yourdir -type f ) |
grep -v /CVS | grep -v /SVN |
while read f; do mv -v $f `echo $f | tr '[A-Z]' '[a-z]'`; done

Benennen Sie zuerst die Verzeichnisse von unten nach oben um, sort -r (wobei -depth nicht verfügbar ist) und dann die Dateien. Dann grep -v / CVS statt find ...- beschneiden, weil es einfacher ist. Bei großen Verzeichnissen kann bei f in ... einige Shell-Puffer überlaufen. Verwenden Sie find ... | während gelesen , um das zu vermeiden.

Und ja, dies wird Dateien blockieren, die sich nur für den Fall unterscheiden ...

pklausner
quelle
Erstens: find YOURDIR -type d | sort -rist zu viel Mühe. Du willst find YOURDIR -depth -type d. Zweitens muss das find -type fMUSS ausgeführt werden, nachdem die Verzeichnisse umbenannt wurden.
Zot
0
find . -depth -name '*[A-Z]*'|sed -n 's/\(.*\/\)\(.*\)/mv -n -v -T \1\2 \1\L\2/p'|sh

Ich habe die hier erwähnten ausführlicheren Skripte nicht ausprobiert, aber keine der einzelnen Befehlszeilenversionen funktionierte auf meinem Synology NAS für mich. renameist nicht verfügbar, und viele der Varianten von findfail schlagen fehl, da sie anscheinend am älteren Namen des bereits umbenannten Pfads festhalten (z. B. wird, wenn ./FOOgefolgt von ./FOO/BAR, das Umbenennen ./FOOin ./foowird weiterhin aufgelistet./FOO/BAR , obwohl dieser Pfad nicht mehr gültig ist). . Der obige Befehl funktionierte für mich ohne Probleme.

Was folgt, ist eine Erklärung für jeden Teil des Befehls:


find . -depth -name '*[A-Z]*'

Dadurch wird jede Datei aus dem aktuellen Verzeichnis (ändern finden ., was auch immer Verzeichnis , das Sie bearbeiten wollen), eine Tiefensuche (zB., Wird es Liste ./foo/barvor ./foo), aber nur für Dateien , die einen Großbuchstaben enthalten. Der -nameFilter gilt nur für den Basisdateinamen, nicht für den vollständigen Pfad. Das wird also ./FOO/BARaber nicht aufgelistet ./FOO/bar. Dies ist in Ordnung, da wir nicht umbenennen möchten ./FOO/bar. Wir möchten zwar umbenennen ./FOO, aber dieses wird später aufgeführt (deshalb -depthist es wichtig).

Dieser Befehl an sich ist besonders nützlich, um die Dateien zu finden, die Sie zuerst umbenennen möchten. Verwenden Sie diese Option nach dem vollständigen Umbenennungsbefehl, um nach Dateien zu suchen, die aufgrund von Kollisionen oder Fehlern mit Dateinamen noch nicht ersetzt wurden.


sed -n 's/\(.*\/\)\(.*\)/mv -n -v -T \1\2 \1\L\2/p'

Dieser Teil liest die von ausgegebenen Dateien findund formatiert sie in einem mvBefehl mit einem regulären Ausdruck. Die -nOption stoppt das sedDrucken der Eingabe, und der pBefehl im regulären Regex zum Suchen und Ersetzen gibt den ersetzten Text aus.

Der reguläre Ausdruck selbst besteht aus zwei Erfassungen: dem Teil bis zum letzten / (dem Verzeichnis der Datei) und dem Dateinamen selbst. Das Verzeichnis bleibt erhalten, aber der Dateiname wird in Kleinbuchstaben umgewandelt. Also, wenn findAusgänge ./FOO/BAR, wird es werden mv -n -v -T ./FOO/BAR ./FOO/bar. Die -nOption mvstellt sicher, dass vorhandene Kleinbuchstaben nicht überschrieben werden. Die -vOption gibt mvjede Änderung aus, die sie vornimmt (oder nicht vornimmt - falls sie ./FOO/barbereits vorhanden ist, gibt sie so etwas wie aus ./FOO/BAR -> ./FOO/BAR, wobei darauf hingewiesen wird, dass keine Änderung vorgenommen wurde). Das -Tist hier sehr wichtig - es behandelt die Zieldatei als Verzeichnis. Dadurch wird sichergestellt, dass das Verzeichnis ./FOO/BARnicht verschoben wird, ./FOO/barwenn es zufällig vorhanden ist.

Verwenden Sie dies zusammen mit find, um eine Liste der Befehle zu erstellen, die ausgeführt werden (praktisch, um zu überprüfen, was getan wird, ohne es tatsächlich zu tun).


sh

Das ist ziemlich selbsterklärend. Es leitet alle generierten mvBefehle an den Shell-Interpreter weiter. Sie können es durch bashoder eine beliebige Hülle nach Ihren Wünschen ersetzen .

Oisyn
quelle
0

Slugify Rename (Regex)

Es ist nicht genau das, wonach das OP gefragt hat, aber was ich auf dieser Seite zu finden gehofft hatte:

Eine "Slugify" -Version zum Umbenennen von Dateien, damit diese URLs ähneln (dh nur alphanumerische Zeichen, Punkte und Bindestriche enthalten):

rename "s/[^a-zA-Z0-9\.]+/-/g" filename
cwd
quelle
2
"nicht genau"? Dies ist überhaupt nicht das, was das OP verlangt hat
Corey Goldberg