Wie alle Ordner und Dateien umbenennen auf Linux in Kleinbuchstaben?
Frage
muss ich rekursiv einen vollständigen Ordnerbaum umbenennen, so dass keine Großbuchstaben überall erscheint (es ist C ++ Sourcecode, aber das sollte keine Rolle spielen). Bonuspunkte für das Ignorieren CVS und SVN Steuer Dateien / Ordner. Bevorzugte Art und Weise würde ein Shell-Skript, da Shell sollte auf jeder Linux-Box zur Verfügung.
Es gibt einige gültige Argumente über Details der Datei Umbenennung waren.
-
Ich denke, Dateien mit dem gleichen Namen in Kleinbuchstaben überschrieben werden soll, ist es das Problem des Benutzers ist. Wenn auf einem Fall-zu ignorieren Dateisystem ausgecheckt würde die ersten mit letzterem überschreibt, auch.
-
würde ich A-Z Zeichen betrachten und verwandeln sie in ein-z, alles andere ist für Probleme nur anrufen (zumindest mit Quellcode).
-
Das Skript wäre notwendig, um einen Build auf einem Linux-System zu laufen, so dass ich denke, Änderungen an CVS oder SVN-Steuerdateien weggelassen werden sollen. Immerhin, es ist nur ein Kratzer Kasse. Vielleicht ist ein "Export" besser geeignet.
Lösung
Eine kurze Version "rename"
Befehl.
find my_root_dir -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
Dies vermeidet Probleme mit Verzeichnissen vor Dateien umbenannt werden und versuchen, Dateien in nicht existierende Verzeichnisse (z "A/A"
in "a/a"
) zu bewegen.
Oder eine ausführlichere Version ohne "rename"
verwendet wird.
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 mit Bewegungsbefehl (z. B.. "svn mv"
).
Andere Tipps
noch klein i ganz wie
rename 'y/A-Z/a-z/' *
Auf Groß- und Kleinschreibung Dateisysteme wie OS X HFS +, werden Sie die -f-Flag hinzuzufügen
rename -f 'y/A-Z/a-z/' *
for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
Versuchen Sie einfach nur folgende, wenn Sie über die Effizienz nicht brauchen Pflege.
zip -r foo.zip foo/*
unzip -LL foo.zip
Die meisten Antworten sind vor gefährlich, weil sie mit Namen enthält, ungeradee Zeichen handelt nicht. Ihre sicherste Wette für diese Art der Sache ist, finden die -print0 Option zu verwenden, die Dateinamen mit ASCII NUL statt \ n beendet wird. Hier stelle ich dieses Skript, das nur Dateien ändern und nicht die Verzeichnisnamen, um nicht finden zu verwirren.
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 mit Leerzeichen, alle Arten von Zitaten, etc. Dies ist wichtig, denn wenn Sie laufen, als root, einer jener anderen Skript auf einem Baum, um die Datei erstellt wird, umfasst:
touch \;\ echo\ hacker::0:0:hacker:\$\'\057\'root:\$\'\057\'bin\$\'\057\'bash
... gut erraten, was ...
Dies funktioniert, wenn Sie bereits oder eingerichtet haben Umbenennungs Befehl (zum Beispiel durch Gebräu installieren in Mac):
rename --lower-case --force somedir/*
Man euch gerne über die Dinge komplizieren ..
Umbenennen 'y / A-Z / a-z / *
Dies funktioniert auf CentOS / Redhat oder anderen Distributionen ohne 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-von-Groß-to-Klein-Zeichen
(in einigen Distributionen der Standard rename
Befehl kommt von util-linux, und das ist ein anderes, nicht kompatibel Werkzeug)
Mit Larry Wall Dateinamen Fixierer
$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/'
(wobei fix ist natürlich das Skript oben)
Die ursprüngliche Frage gestellt zu ignorieren SVN und CVS Verzeichnisse, die durch Zugabe von -prune zu dem Befehl find durchgeführt werden können. Z. B zu ignorieren CVS:
find . -name CVS -prune -o -exec mv '{}' `echo {} | tr '[A-Z]' '[a-z]'` \; -print
[Bearbeiten] Ich habe versucht, diese aus, und die Einbettung die Kleine Übersetzung innerhalb des Funds nicht aus Gründen nicht funktioniert verstehe ich nicht wirklich. So ändern Sie diese an:
$> cat > tolower
#!/bin/bash
mv $1 `echo $1 | tr '[:upper:]' '[:lower:]'`
^D
$> chmod u+x tolower
$> find . -name CVS -prune -o -exec tolower '{}' \;
Ian
Hier ist meine suboptimale Lösung, einen 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 einige Änderungen vorgenommen, so weit auf den Vorschlägen basiert. Jetzt Ordner richtig alle umbenannt werden, mv nicht, Fragen zu stellen, wenn Berechtigungen nicht übereinstimmen, und CVS Ordner werden nicht umbenannt (CVS Control-Dateien in diesem Ordner noch umbenannt werden, leider).
Edit: Da „-depth finden“ und „finden | sort -r“ sowohl die Ordner-Liste in einem nutzbaren zurückkehren, um für das Umbenennen, ich für die Suche Ordner mit „-depth“ Beliebte
.Dies ist ein kleiner Shell-Skript, das tut, was Sie angefordert:
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 -depth Aktion in der ersten Entdeckung.
Die zuvor perfekt aus der Box geschrieben arbeiten oder mit einigen Anpassungen für einfache Fälle, aber es gibt einige Situationen, die Sie berücksichtigen möchten, bevor die Batch-Umbenennen ausführen:
-
Was soll passieren, wenn Sie zwei oder mehr Namen auf der gleichen Ebene in der Pfadhierarchie, die von Fall nur darin unterscheiden, wie
ABCdef
,abcDEF
undaBcDeF
? Sollte das Umbenennungs Skript abbrechen oder nur warnen und fortfahren? -
Wie definieren Sie Kleinbuchstaben für Nicht-US-ASCII-Namen? Wenn solche Namen vorhanden sein könnten, sollte man prüfen und verstehen sich inklusive Pass zuerst durchgeführt werden?
-
Wenn Sie einen Umbenennungsvorgang auf CVS oder SVN Arbeitskopien ausführen, Sie möglicherweise beschädigt die Arbeitskopie, wenn Sie den Fall auf Datei- oder Verzeichnisnamen ändern. Sollte das Skript auch interne Verwaltungsdateien wie .svn / Einträge oder CVS / Entries finden und einstellen?
for f in `find -depth`; do mv ${f} ${f,,} ; done
find -depth
druckt jede Datei und Verzeichnis, mit einem vor dem Verzeichnis gedruckten Inhalt des Verzeichnisses selbst. ${f,,}
Kleinbuchstaben umwandelt den Dateinamen.
Mit MacOS,
Installieren Sie das Paket rename
,
brew install rename
Die Verwendung,
find . -iname "*.py" -type f | xargs -I% rename -c -f "%"
Mit diesem Befehl alle Dateien mit einer Erweiterung *.py
finden und wandelt die Dateinamen in Kleinbuchstaben.
`f` - forces a rename
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
Nicht tragbar, Zsh nur, aber ziemlich prägnant.
Stellen Sie zunächst sicher zmv
geladen wird.
autoload -U zmv
Also, stellen Sie sicher, dass extendedglob
auf:
setopt extendedglob
Dann verwenden:
zmv '(**/)(*)~CVS~**/CVS' '${1}${(L)2}'
rekursiv Klein-Dateien und Verzeichnisse, in denen der Name nicht ist CVS .
In OSX, mv -f zeigt "gleiche Datei" Fehler, so dass ich umbenennen zweimal.
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
Ich brauchte diese auf einem Cygwin-Setup auf Windows 7 zu tun und fand, dass ich Syntaxfehler mit den Vorschlägen von oben bekam ich versuchte, (obwohl ich eine funktionierende Option verpaßt habe) aber diese Lösung aus gerade von ubutu Foren aus der Dose gearbeitet: -)
ls | while read upName; do loName=`echo "${upName}" | tr '[:upper:]' '[:lower:]'`; mv "$upName" "$loName"; done
(nb ich vorher Leerzeichen ersetzen hatte Unterstrichen mit mit
for f in *\ *; do mv "$f" "${f// /_}"; done
würde ich für Python in dieser Situation erreichen, optimistischen Pfade ohne Leerzeichen oder Schrägstriche unter der Annahme zu vermeiden. Ich habe auch festgestellt, dass python2
neigt als rename
an mehr Orten installiert werden.
#!/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])
Langwierige Aber "Works With No Surprises & No Installationen"
Dieses Skript Griffe Dateinamen mit Leerzeichen, Anführungszeichen, andere ungewöhnlichen Zeichen und Unicode arbeitet auf Groß- und Kleinschreibung von Dateisystemen und die meisten Unix-y-Umgebungen , die bash und awk installiert ( dh fast alle). Er berichtet auch Kollisionen, wenn eine (den Dateinamen in Großbuchstaben zu verlassen) und natürlich umbenennt beide Dateien & Verzeichnisse und arbeitet rekursiv. Endlich ist es sehr anpassungsfähig: Sie können den Befehl find zwicken die Dateien zum Ziel / dirs Sie möchten und Sie können awk zwicken anderen Namen Manipulationen zu tun. Beachten Sie, dass durch „Griffe Unicode“ Ich meine, dass es wird in der Tat ihren Fall konvertieren (nicht ignorieren sie 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 / durch~~POS=TRUNC-files-mit-Räume-in-the-Namen
Einfachstes Ansatz, den ich auf MacOSX fand, war das Umbenennungs Paket zu verwenden, um von http://plasmasturm.org/code / umbenennen / :
brew install rename
rename --force --lower-case --nows *
-. Kraft Umbenennen, selbst wenn eine Datei mit dem Zielnamen bereits vorhanden
-. Klein Convert Dateinamen Kleinbuchstaben
-. Nows Ersetzen Sie alle Folgen von Leerzeichen im Dateinamen mit einzelnen Unterstrichen
( 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
Sie zuerst die Verzeichnisse unten umbenennen bis sort -r (wobei -depth nicht verfügbar ist), dann die Dateien. Dann grep -v / CVS statt finden ...- prune , weil es einfacher ist. Für große Verzeichnisse, für f in ... können einige Shell-Puffer überlaufen. Verwenden Sie finden ... | lesen, während zu vermeiden, dass.
Und ja, diese Dateien verprügeln, die nur im Fall unterscheiden ...
Slugify Rename (regex)
Nicht genau das, was die OP fragte nach, aber was ich habe gehofft, dass auf dieser Seite zu finden:
A „slugify“ -Version für das Umbenennen von Dateien, so dass sie ähnlich sind URLs
(Das heißt nur alphanumerische, Punkte und Striche):
rename "s/[^a-zA-Z0-9\.]+/-/g" filename
Wenn Sie Arch Linux , können Sie rename
Paket von AUR
die renamexm
Befehl als /usr/bin/renamexm
ausführbare und seine Handbuch Seite mit.
Es ist wirklich leistungsfähiges Werkzeug, um schnell Dateien und Verzeichnisse zu umbenennen.
Konvertieren in Kleinbuchstaben
rename -l Developers.mp3 # or --lowcase
Konvertieren zu Grossbuchstaben
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 Probe holen Developers.mp3 Datei von hier wenn erforderlich;)
Niemand darauf hindeutet, typeset?
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
Auf Windows-Emulationen wie git bash scheitern kann dies, weil Windows nicht zwischen Groß- und Klein unter der Haube. Für diejenigen, fügen Sie einen Schritt, der mv die Datei zuerst auf einen anderen Namen ist, wie „$ old.tmp“, dann auf neue $.
Das funktioniert gut auf macOS auch:
ruby -e "Dir['*'].each { |p| File.rename(p, p.downcase) }"
find . -depth -name '*[A-Z]*'|sed -n 's/\(.*\/\)\(.*\)/mv -n -v -T \1\2 \1\L\2/p'|sh
Ich habe nicht die aufwändigere Skripte versucht hier erwähnt, aber keine der einzelnen Kommandozeilen-Versionen funktionierte für mich auf meinem Synology NAS. rename
nicht verfügbar ist, und viele der Variationen von find
scheitern, weil es zu dem älteren Namen des bereits umbenannt Pfades zu bleiben scheint (zB wenn es ./FOO
von ./FOO/BAR
gefolgt findet, ./FOO
Umbenennung wird ./foo
noch ./FOO/BAR
zur Liste fortsetzen, obwohl dieser Weg ist nicht mehr gültig). Obiger Befehl funktionierte für mich ohne Probleme.
Was folgt, ist eine Erklärung der einzelnen Teile des Befehls:
find . -depth -name '*[A-Z]*'
Dies wird jede Datei aus dem aktuellen Verzeichnis (ändern .
zu, was Verzeichnis, das Sie bearbeiten mögen) finden, eine Tiefensuche (zB., Wird es ./foo/bar
vor ./foo
Liste), aber nur für Dateien, die einen Groß enthalten Charakter. Der -name
Filter gilt nur für die Basisdateinamen, nicht der vollständige Pfad. So wird diese Liste ./FOO/BAR
aber nicht ./FOO/bar
. Das ist in Ordnung, da wir ./FOO/bar
nicht umbenennen möchten. Wir wollen allerdings ./FOO
umbenennen, sondern dass man aufgeführt wird später (aus diesem Grund -depth
wichtig ist).
Diese comand an sich ist besonders nützlich, um die Dateien zu finden, die Sie in erster Linie umbenennen möchten. Verwenden Sie diese nach dem vollständigen Umbenennungs Befehl nach Dateien zu suchen, die noch nicht wegen Dateinamendopplungen oder Fehler ersetzt.
sed -n 's/\(.*\/\)\(.*\)/mv -n -v -T \1\2 \1\L\2/p'
Dieser Teil liest die von find
ausgegebenen Dateien und formatiert sie in einem mv
Befehl, um einen regulären Ausdruck. Die -n
Option beendet sed
von Druck des Eingangs und der p
Befehl bei der Suche und Ersetzen Regex gibt den zu ersetzenden Text.
Die Regex selbst besteht aus zwei Aufnahmen: der Teil bis zum letzten / (die das Verzeichnis der Datei ist), und der Dateiname selbst. Das Verzeichnis ist intakt, aber der Dateiname wird umgewandelt in Kleinbuchstaben. Also, wenn find
./FOO/BAR
gibt, wird es mv -n -v -T ./FOO/BAR ./FOO/bar
werden. Die -n
Möglichkeit mv
stellt sicher, dass bestehende Klein Dateien nicht überschrieben werden. Die -v
Option macht mv
Ausgabe jede Änderung, dass es macht (oder macht es nicht - wenn ./FOO/bar
bereits vorhanden ist, gibt es so etwas wie ./FOO/BAR -> ./FOO/BAR
, unter Hinweis darauf, dass keine Änderung vorgenommen wurde). Die -T
ist hier sehr wichtig - es behandelt die Zieldatei als Verzeichnis. Dadurch wird sichergestellt, dass ./FOO/BAR
nicht in ./FOO/bar
bewegt, wenn das Verzeichnis existiert passiert.
Verwenden Sie diese Option zusammen mit find
eine Liste von Befehlen zu erzeugen, die (praktisch, um zu überprüfen, was ohne tatsächlich zu tun es getan wird) ausgeführt werden
sh
Dieses ziemlich selbsterklärend. Er leitet alle erzeugten mv
Befehle an die Shell-Interpreter. Sie können es mit bash
oder jeder Schale von einer Vielzahl von Design ersetzen.