Comment renommer tous les dossiers et fichiers en minuscules sous Linux?

je dois renommer un arbre de dossiers complet de façon récursive afin qu'aucune lettre en majuscule n'apparaisse nulle part (c'est le code source C++, mais cela ne devrait pas avoir d'importance). Points Bonus pour ignorer CVS et les fichiers/dossiers de contrôle SVN. La méthode préférée serait un script shell, puisque shell devrait être disponible sur N'importe quelle machine Linux.

il y avait quelques arguments valables sur les détails du renommage du fichier.

  1. je pense que les fichiers avec la même minuscule les noms doivent être réécrits, c'est le problème de l'utilisateur. Une fois vérifié sur un système de fichier ignorant cas serait écraser le premier avec le dernier, aussi.

  2. je considérerais les caractères A-Z et les transformerais en A-z, tout le reste appelle juste pour des problèmes (au moins avec le code source).

  3. le script serait nécessaire pour exécuter une construction sur un système Linux, donc je pense que des changements aux fichiers de contrôle CVS ou SVN doit être omis. Après tout, c'est juste une égratignure de la caisse. Peut-être une "exportation" est plus approprié.

140
demandé sur dsm 2008-09-30 14:25:17

24 réponses

une version concise utilisant la commande "rename" .

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

cela évite les problèmes avec les répertoires étant renommés avant les fichiers et essayant de déplacer des fichiers dans les répertoires non existants (par exemple "A/A" dans "a/a" ).

Ou, une version plus détaillée, sans l'aide de "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.

ce dernier permet une plus grande flexibilité avec la commande move (E. G. "svn mv" ).

153
répondu Alex B 2008-09-30 12:03:32

encore plus petit j'aime bien

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

sur les systèmes de fichiers insensibles à la casse tels que HFS+ D'OS X, vous voudrez ajouter le drapeau-f

rename -f 'y/A-Z/a-z/' *
219
répondu tristanbailey 2014-12-01 11:37:29
for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
73
répondu Swaroop C H 2016-08-10 12:51:58

essayez simplement de suivre si vous n'avez pas besoin de se soucier de l'efficacité.

zip -r foo.zip foo/*
unzip -LL foo.zip
58
répondu Ginhing 2015-06-09 14:09:34

la plupart des réponses ci-dessus sont dangereuses parce qu'elles ne traitent pas de noms contenant des caractères impairs. Votre pari le plus sûr pour ce genre de chose est d'utiliser l'option find's-print0, qui terminera les noms de fichiers avec ascii NUL au lieu de \N. Ici, je soumets ce script, qui ne modifie que les fichiers et pas les noms de répertoire pour ne pas confondre find.

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

je l'ai testé et il fonctionne avec des noms de fichiers contenant des espaces, toutes sortes de citations, etc. C'est important parce que si vous exécutez, comme root, un de ces Autres scripts sur un arbre qui inclut le fichier créé par:

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

... eh bien, devinez quoi ...

14
répondu niXar 2008-09-30 12:34:13

cela fonctionne si vous avez déjà ou mis en place la commande renommer (par exemple via brew install En Mac):

rename --lower-case --force somedir/*
10
répondu alemol 2018-04-19 15:46:47

vous aimez compliquer les choses..

renommer 'y / A-Z / A-z/' *

9
répondu Stephen 2017-02-18 10:54:18

à l'Aide de Larry Wall nom du fichier fixateur

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

c'est aussi simple que

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

(où fix est bien sûr le script ci-dessus)

4
répondu agnul 2008-09-30 10:50:14

la question initiale demandait d'ignorer les répertoires SVN et CVS, ce qui peut être fait en ajoutant-prune à la commande find. Par exemple, pour ignorer CVS:

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

[edit] j'ai essayé cela, et l'intégration de la traduction minuscule à l'intérieur de la trouvaille n'a pas fonctionné pour des raisons que je ne comprends pas vraiment. Modifier comme suit:

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

Ian

4
répondu Ian Dickinson 2008-09-30 11:42:40

voici ma solution sous-optimale, en utilisant un script Shell bash:

#!/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: j'ai fait quelques modifications basées sur les suggestions jusqu'à présent. Maintenant les dossiers sont tous renommés correctement, mv ne pose pas de questions quand les permissions ne correspondent pas, et les dossiers CVS ne sont pas renommés (les fichiers de contrôle CVS à l'intérieur de ce dossier sont encore renommés, malheureusement).

Edit: depuis "find-depth" et "find | sort-r" Tous les deux renvoient la liste des dossiers dans un ordre utilisable pour renommer, j'ai préféré utiliser "- depth " pour la recherche de dossiers.

4
répondu vividos 2008-09-30 13:07:14

c'est un petit script shell qui fait ce que vous avez demandé:

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

Note la profondeur d'action à la première de trouver.

3
répondu tzot 2008-09-30 10:54:48

cela fonctionne sur les distributions CentOS / Redhat ou autres sans le script Perl rename :

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

Source: https://linuxconfig.org/rename-all-files-from-uppercase-to-lowercase-characters

(dans certains cas, la commande par défaut rename vient d'util-linux, et c'est un outil différent et incompatible)

3
répondu Pere 2016-08-10 12:55:43

le précédemment affiché fonctionnera parfaitement hors de la boîte ou avec quelques ajustements pour les cas simples, mais il ya des situations que vous pourriez vouloir prendre en compte avant d'exécuter le lot renommer:

  1. que se passe-t-il si vous avez deux ou plusieurs noms au même niveau dans la hiérarchie des chemins qui ne diffèrent que par cas, tels que ABCdef , abcDEF et aBcDeF ? Le script renommé devrait-il abandonner ou simplement avertir et continuer?

  2. Comment définissez-vous les minuscules pour les noms non US-ASCII? Si de tels noms peuvent être présents, devrait-on effectuer une vérification et exclure la réussite en premier?

  3. si vous effectuez une opération de renommage sur des copies de travail CVS ou SVN, vous risquez de corrompre la copie de travail si vous changez le cas sur les noms de fichiers ou de répertoires. Si le script trouve et ajuste aussi des dossiers administratifs internes tels que .svn / entrées ou CVS / entrées?

2
répondu Mihai Limbășan 2008-09-30 10:57:44

Avec MacOS,

Installer rename package

brew install rename

Use,

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

cette commande trouve tous les fichiers avec une extension *.py et convertit les noms de fichiers en minuscules.

`f` - forces a rename

par exemple,

$ 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
répondu akilesh raj 2018-09-13 08:05:35

pas portable, Zsh seulement, mais assez concis.

D'abord, assurez-vous que zmv est chargé.

autoload -U zmv

aussi, assurez-vous que extendedglob est sur:

setopt extendedglob

puis utiliser:

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

pour les fichiers et répertoires en minuscules lorsque le nom n'est pas CVS .

1
répondu benjwadams 2013-07-18 18:45:33

dans OSX, mv-f affiche une erreur" même fichier", donc j'ai renommé deux fois.

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
répondu Jonghee Park 2015-03-25 06:25:39

je voudrais atteindre python dans cette situation, pour éviter d'assumer de façon optimiste des chemins sans espaces ou des entailles. J'ai également constaté que python2 tend à être installé dans plus d'endroits que 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
répondu John Foley 2016-01-31 18:07:20
for f in `find -depth`; do mv ${f} ${f,,} ; done

find -depth imprime chaque fichier et répertoire, avec le contenu d'un répertoire imprimé avant le répertoire lui-même. ${f,,} réduit le nom du fichier.

1
répondu Chris Schierkolk 2016-02-25 21:06:17
( 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

renommer D'abord les répertoires bas vers le haut trier-R (où-la profondeur n'est pas disponible), puis les fichiers. Puis grep-v /CVS au lieu de find ...- prune parce que c'est plus simple. Pour les grands répertoires, pour F in ... peut déborder certains tampons shell. Utilisez find ... / tout en lisant pour éviter cela.

et oui, cela clouera les fichiers qui diffèrent seulement dans le cas...

0
répondu pklausner 2008-09-30 11:26:32

Slugify Renommer (regex)

pas exactement ce que l'OP demandait, mais ce que j'espérais trouver sur cette page:

a "slugify" version pour renommer les fichiers afin qu'ils soient similaires aux URLs

(c'est à dire uniquement inclure alphanumériques, de points et de tirets):

rename "s/[^a-zA-Z0-9\.]+/-/g" filename
0
répondu cwd 2015-02-28 02:32:26

j'avais besoin de faire cela sur une configuration de cygwin sur Windows 7 et j'ai constaté que j'ai eu des erreurs de syntaxe avec les suggestions ci-dessus que j'ai essayé (bien que j'ai peut-être manqué une option de travail) cependant cette solution directement de forums ubutu travaillé à partir de la can: -)

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

( nb: j'avais déjà remplacer les espaces par des caractères de soulignement à l'aide de

for f in *\ *; do mv "$f" "${f// /_}"; done
0
répondu jacanterbury 2015-05-20 10:42:26

si vous utilisez Arch Linux , vous pouvez installer rename paquet de AUR qui fournit renamexm commande comme /usr/bin/renamexm exécutable et un son manuel page avec elle.

c'est un outil vraiment puissant pour renommer rapidement des fichiers et des répertoires.

convertir en minuscules

rename -l Developers.mp3 # or --lowcase

Convertir en majuscule

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

autres options

-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

Vous permet de récupérer l'échantillon des Développeurs.mp3 fichier de ici , si nécessaire ;)

0
répondu w17t 2017-06-22 21:40:57

personne ne suggère de composition?

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

sur les émulations de fenêtres comme git bash cela peut échouer parce que les fenêtres ne sont pas sensibles à la casse sous le capot. Pour ceux-là, ajouter une étape que mv est le fichier à un autre nom d'abord, comme "$old.tmp", puis à $nouveau.

0
répondu Paul Hodges 2017-09-29 16:09:58

Longue Mais "Fonctionne Avec Pas De Surprises, Pas De Des Installations"

ce script gère les noms de fichiers avec des espaces, des guillemets, d'autres caractères inhabituels et Unicode, fonctionne sur des systèmes de fichiers insensibles à la casse et la plupart des environnements Unix-y qui ont bash et awk installés (c'est-à-dire presque tous). Il signale également les collisions éventuelles (en laissant le nom du fichier en majuscule) et bien sûr renomme les fichiers et répertoires et fonctionne de manière récursive. Enfin, il est très adaptable: vous pouvez modifier la commande find pour cibler les fichiers/dirs que vous souhaitez et vous pouvez modifier awk pour faire d'autres manipulations de noms. Notez que par " handles Unicode "je veux dire qu'il va effectivement convertir leur cas (ne pas les ignorer comme les réponses qui utilisent 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 {} +

références

mon script est basé sur ces excellentes réponses:

https://unix.stackexchange.com/questions/9496/looping-through-files-with-spaces-in-the-names

comment convertir une chaîne en minuscules en Bash?

0
répondu ndemou 2018-09-25 21:05:25