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.

  1. 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.

  2. würde ich A-Z Zeichen betrachten und verwandeln sie in ein-z, alles andere ist für Probleme nur anrufen (zumindest mit Quellcode).

  3. 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.

War es hilfreich?

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:

  1. 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 und aBcDeF? Sollte das Umbenennungs Skript 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 man prüfen und verstehen sich inklusive Pass zuerst durchgeführt werden?

  3. 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

Wie eine Zeichenfolge konvertieren Fall zu senken, in bash?

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

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top