it-swarm.com.de

Wie kann man unter Linux alle Ordner und Dateien in Kleinbuchstaben umbenennen?

Ich muss einen vollständigen Ordnerbaum rekursiv umbenennen, sodass an keiner Stelle Großbuchstaben angezeigt werden (C++ - Quellcode, aber das sollte keine Rolle spielen). Bonuspunkte für das Ignorieren von CVS- und SVN-Steuerungsdateien/-ordnern. Der bevorzugte Weg wäre ein Shell-Skript, da Shell in jeder Linux-Box verfügbar sein sollte.

Es gab einige gültige Argumente zu Details der Dateiumbenennung.

  1. Ich denke, Dateien mit den gleichen Kleinbuchstaben sollten überschrieben werden, das ist das Problem des Benutzers. Beim Auschecken in einem Fall, in dem das Dateisystem ignoriert wurde, wurde das erste Dateisystem ebenfalls mit dem letzten überschrieben.

  2. Ich würde A-Z-Zeichen in Betracht ziehen und sie in A-Z umwandeln, alles andere fordert nur Probleme (zumindest mit Quellcode).

  3. Das Skript wäre zum Ausführen eines Builds auf einem Linux-System erforderlich. Ich denke, Änderungen an CVS- oder SVN-Steuerungsdateien sollten daher weggelassen werden. Immerhin ist es nur eine Kratzerkasse. Vielleicht ist ein "Export" eher angebracht.

151
vividos

Eine prägnante Version, die den Befehl "rename" verwendet.

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

Dies vermeidet Probleme mit Verzeichnissen, die vor Dateien umbenannt werden und versuchen, Dateien in nicht vorhandene Verzeichnisse zu verschieben (z. B. "A/A" in "a/a").

Oder eine ausführlichere Version ohne "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

P. S.

Letzteres ermöglicht mehr Flexibilität beim Verschieben (z. B. "svn mv").

158
Alex B

kleiner noch mag ich ziemlich 

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

Auf Dateisystemen, bei denen die Groß- und Kleinschreibung nicht beachtet wird, z. B. HFS + von OS X, sollten Sie das Flag -f hinzufügen 

rename -f 'y/A-Z/a-z/' *
232
tristanbailey
for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
79
Swaroop C H

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

Zip -r foo.Zip foo/*
unzip -LL foo.Zip
62
Ginhing

Die meisten der obigen 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 der -print0-Option von find, die Dateinamen mit ascii NUL anstelle von\n beendet. Hier sende ich dieses Skript ein, das nur Dateien und nicht Verzeichnisnamen ändert, um find nicht zu verwechseln. 

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, alle Arten von Anführungszeichen usw. enthalten. Dies ist wichtig, weil, wenn Sie als root ein anderes Skript in einer Baumstruktur ausführen, die die folgende Datei enthält:

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

... Rate mal ...

14
niXar

Dies funktioniert, wenn Sie den Befehl umbenennen bereits eingerichtet oder eingerichtet haben (z. B. durch Brühinstallation auf einem Mac):

rename --lower-case --force somedir/*
12
alemol

Mann euch Jungs überkomplizieren Dinge .. 

umbenennen von 'y/A-Z/a-z /' *

9
Stephen

Dies funktioniert auf CentOS/Redhat oder anderen Distributionen ohne das rename Perl-Skript:

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

Quelle: https://linuxconfig.org/rename-all-files-from-uppercase-to-lowercase-zeichen

(In einigen Distros kommt der Standardbefehl rename von util-linux, und das ist ein anderes, inkompatibles Werkzeug)

6
Pere

In der ursprünglichen Frage wurden die SVN- und CVS-Verzeichnisse ignoriert. Dies kann durch Hinzufügen von -Prune zum Befehl find geschehen. Zum Beispiel, um CVS zu ignorieren:

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

Ich habe es ausprobiert, und das Einbetten der Kleinbuchstaben-Übersetzung in den Fund funktionierte aus Gründen, die ich eigentlich nicht verstehe. Also ändere dies zu:

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

Ian

4
Ian Dickinson

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

Edit: Ich habe aufgrund der bisherigen Vorschläge einige Änderungen vorgenommen. Jetzt werden alle Ordner korrekt umbenannt, mv stellt keine Fragen, wenn die Berechtigungen nicht übereinstimmen, und CVS-Ordner werden nicht umbenannt (CVS-Steuerungsdateien in diesem Ordner werden leider immer noch umbenannt).

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

4
vividos

Verwenden Sie den Dateinamen-Fixierer von Larry Wall

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

es ist so einfach wie

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

(wo fix ist natürlich das obige Skript)

4
agnul

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 -depth in der ersten Suche.

3
tzot

Die zuvor veröffentlichten Funktionen funktionieren einwandfrei oder mit wenigen Anpassungen für einfache Fälle. Es gibt jedoch Situationen, in denen Sie vor dem Ausführen der Stapelumbenennung einige Punkte berücksichtigen sollten:

  1. Was soll passieren, wenn Sie zwei oder mehr Namen auf derselben Ebene in der Pfadhierarchie haben, die sich nur von Fall zu Fall unterscheiden, wie ABCdef, abcDEF und aBcDeF? Soll das Umbenennungsskript abbrechen oder einfach warnen und fortfahren?

  2. Wie definieren Sie Kleinbuchstaben für Nicht-US-ASCII-Namen? Wenn solche Namen vorhanden sein könnten, sollte zuerst ein Pass geprüft und der Pass ausgeschlossen werden?

  3. Wenn Sie einen Umbenennungsvorgang für CVS- oder SVN-Arbeitskopien ausführen, können Sie die Arbeitskopie beschädigen, wenn Sie die Groß- und Kleinschreibung der Datei- oder Verzeichnisnamen ändern. Soll das Skript auch interne Verwaltungsdateien wie .svn/entries oder CVS/entry finden und anpassen?

2

Mit MacOS

Installieren Sie das Paket rename.

brew install rename

Benutzen,

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

Dieser Befehl findet alle Dateien mit der Erweiterung *.py und konvertiert die Dateinamen in Kleinbuchstaben.

`f` - forces a rename

Zum Beispiel,

$ 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
2
akilesh raj

Ich würde in dieser Situation nach Python greifen, um optimistisch zu vermeiden, Wege ohne Leerzeichen oder Schrägstriche anzunehmen. Ich habe auch festgestellt, dass python2 an mehr Stellen installiert wird als 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])
1
John Foley

In OSX zeigt mv -f den Fehler "gleiche Datei", so dass ich zweimal umbenenne.

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
1
Jonghee Park

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

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

--Umbenennen erzwingen, auch wenn bereits eine Datei mit dem Zielnamen vorhanden ist.

--lower-case Konvertiert Dateinamen in Kleinbuchstaben.

--nows Ersetzen Sie alle Whitespace-Sequenzen im Dateinamen durch einzelne Unterstriche.

1
Kim T
for f in `find -depth`; do mv ${f} ${f,,} ; done

find -depth druckt jede Datei und jedes Verzeichnis, wobei der Inhalt eines Verzeichnisses vor dem Verzeichnis selbst gedruckt wird. ${f,,} verkleinert den Dateinamen.

1

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

Stellen Sie zunächst sicher, dass zmv geladen ist.

autoload -U zmv

Stellen Sie außerdem sicher, dass extendedglob eingeschaltet ist:

setopt extendedglob

Dann benutze:

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

Um rekursiv Kleinbuchstaben und Verzeichnisse zu erstellen, bei denen der Name nichtCVSist.

1
benjwadams
find . -depth -name '*[A-Z]*'|sed -n 's/\(.*\/\)\(.*\)/mv -n -v -T \1\2 \1\L\2/p'|sh

Ich habe die ausführlicheren Skripts, die hier erwähnt werden, nicht ausprobiert, aber keine der einzelnen Befehlszeilenversionen funktionierte für mich auf meinem Synology NAS. rename ist nicht verfügbar, und viele der Variationen von find schlagen fehl, da sie anscheinend an dem älteren Namen des bereits umbenannten Pfads verbleiben (z. B. ./FOO, gefolgt von ./FOO/BAR, umbenennen ./FOO bis ./foo listet weiterhin ./FOO/BAR auf, obwohl dieser Pfad nicht mehr gültig ist). Der obige Befehl funktionierte für mich ohne Probleme.

Was folgt, ist eine Erklärung jedes Teils des Befehls:


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

Dadurch wird jede Datei aus dem aktuellen Verzeichnis (ändern Sie . in das Verzeichnis, das Sie verarbeiten möchten) mit einer Tiefensuche gefunden (z. B. ./foo/bar vor ./foo). , aber nur für Dateien, die Großbuchstaben enthalten. Der Filter -name gilt nur für den Namen der Basisdatei, nicht für den vollständigen Pfad. Dies wird also ./FOO/BAR aber nicht ./FOO/bar auflisten. Dies ist in Ordnung, da wir ./FOO/bar nicht umbenennen möchten. Wir möchten zwar ./FOO umbenennen, aber das ist später aufgeführt (deshalb ist -depth wichtig).

Dieser Befehl an sich ist besonders nützlich, um die Dateien zu finden, die Sie zuerst umbenennen möchten. Verwenden Sie dies nach dem Befehl zum vollständigen Umbenennen, um nach Dateien zu suchen, die aufgrund von Dateinamenkollisionen oder -fehlern immer noch nicht ersetzt wurden.


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

Dieser Teil liest die von find ausgegebenen Dateien und formatiert sie mit einem regulären Ausdruck in einem mv-Befehl. Die Option -n stoppt, dass sed die Eingabe druckt, und der Befehl p im Such-und-Ersetzen-Regex gibt den ersetzten Text aus.

Der Regex selbst besteht aus zwei Captures: dem Teil bis zum letzten/(das ist das Verzeichnis der Datei) und dem Dateinamen. Das Verzeichnis bleibt erhalten, der Dateiname wird jedoch in Kleinbuchstaben umgewandelt. Wenn also find./FOO/BAR ausgibt, wird es mv -n -v -T ./FOO/BAR ./FOO/bar. Die Option -n von mv sorgt dafür, dass vorhandene Dateien in Kleinbuchstaben nicht überschrieben werden. Mit der Option -v wird mv bei jeder Änderung ausgegeben (oder nicht vorgenommen - wenn ./FOO/bar bereits vorhanden ist, wird etwas wie ./FOO/BAR -> ./FOO/BAR ausgegeben, wobei darauf hingewiesen wird, dass keine Änderung vorgenommen wurde). Der -T ist hier sehr wichtig - er behandelt die Zieldatei als Verzeichnis. Dadurch wird sichergestellt, dass ./FOO/BAR nicht in ./FOO/bar verschoben wird, wenn das Verzeichnis tatsächlich vorhanden ist.

Verwenden Sie dies zusammen mit find, um eine Liste von Befehlen 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 mv-Befehle an den Shell-Interpreter weiter. Sie können es durch bash oder eine beliebige Shell Ihrer Wahl ersetzen.

0
oisyn
( 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 umsort -r (wobei -depth nicht verfügbar ist), dann die Dateien . Dann grep -v/CVS statt find ...- Prune weil es einfacher ist . Bei großen Verzeichnissen kann für f in ... einige Shell-Puffer überlaufen . Verwenden Sie find ... | während lesen um das zu vermeiden.

Und ja, das wird Akten verderben, die sich nur unterscheiden, wenn ...

0
pklausner

Wenn Sie Arch Linux verwenden, können Sie rename package von AUR installieren, das renamexm als /usr/bin/renamexm ausführbare Datei und eine dazugehörige manual - Seite bereitstellt.

Es ist ein sehr leistungsfähiges Werkzeug, um Dateien und Verzeichnisse schnell umzubenennen.

Konvertieren Sie in Kleinbuchstaben

rename -l Developers.mp3 # or --lowcase

Konvertieren Sie in den UPPER-Fall

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 # substite string on pattern

--yes # Confirm all actions

Sie können die Beispieldatei Developers.mp3 von hier herunterladen, falls erforderlich;)

0
w17t

Ich musste dies auf einem cygwin-Setup unter Windows 7 durchführen und fand heraus, dass ich Syntaxfehler mit den von oben ausgeführten Vorschlägen bekam (obwohl ich möglicherweise eine funktionierende Option verpasst habe), jedoch diese Lösung direkt aus ubutu-Foren funktioniert aus der Dose :-)

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

(Anmerkung: Ich hatte vorher Whitespace durch Unterstriche ersetzt

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

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

Dieses Skript behandelt Dateinamen mit Leerzeichen, Anführungszeichen, anderen ungewöhnlichen Zeichen und Unicode. Es kann auf Groß- und Kleinschreibung von Dateisystemen und den meisten Unix-y-Umgebungen angewendet werden, auf denen bash und awk installiert sind (d. H. Fast alle). Es meldet auch eventuelle Kollisionen (wobei der Dateiname in Großbuchstaben bleibt) und benennt natürlich sowohl Dateien als auch Verzeichnisse um und arbeitet rekursiv. Endlich ist es sehr anpassungsfähig: Sie können den Befehl find mit den gewünschten Dateien und Verzeichnissen optimieren, und Sie können awk für andere Namensmanipulationen anpassen. Beachten Sie, dass mit "behandelt Unicode" ich meine, dass sie ihren Fall tatsächlich konvertieren wird (nicht ignorieren wie Antworten, die tr verwenden).

# 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 {} +

Referenzen

Mein Skript basiert auf diesen hervorragenden Antworten:

https://unix.stackexchange.com/questions/9496/looping-through-files-mit-spaces-in-der-namen -

Wie konvertiere ich einen String in Bash in Kleinbuchstaben?

0
ndemou

Das funktioniert auch auf macOS gut:

Ruby -e "Dir['*'].each { |p| File.rename(p, p.downcase) }"
0
Chris

Slugify Umbenennen (Regex)

Nicht genau das, wonach das OP gefragt hat, aber was ich auf dieser Seite zu finden hoffte: 

Eine "Slugify" -Version zum Umbenennen von Dateien, sodass sie URLs ähneln
(d. h. nur alphanumerische Zeichen, Punkte und Bindestriche enthalten):

rename "s/[^a-zA-Z0-9\.]+/-/g" filename
0
cwd

Niemand schlägt Satz vor? 

typeset -l new        # always lowercase
find $topPoint |      # not using xargs to make this more readable
  while read old
  do mv "$old" "$new" # quotes for those annoying embedded spaces
  done

Bei Windows-Emulationen wie Git-Bash kann dies fehlschlagen, da die Groß- und Kleinschreibung nicht unter der Haube ist. Fügen Sie für diese einen Schritt hinzu, in dem die Datei mv zuerst unter einem anderen Namen wie "$ old.tmp" und dann in $ new gespeichert wird. 

0
Paul Hodges