Mise en minuscule de tous les répertoires d'un répertoire


12

Je veux mettre en minuscule le nom de chaque répertoire sous un répertoire. Avec quelles commandes puis-je faire cela?

Réponses:


10

Tous les répertoires à un niveau, ou récursivement?

Zsh

À un niveau:

autoload zmv
zmv -o-i -Q 'root/(*)(/)' 'root/${1:l}'

Récursivement:

zmv -o-i -Q 'root/(**/)(*)(/)' 'root/$1${2:l}'

Explications: zmvrenomme les fichiers correspondant à un modèle en fonction du texte de remplacement donné. -o-ipasse l' -ioption à chaque mvcommande sous le capot (voir ci-dessous). Dans le texte de remplacement, $1, $2, etc, sont les groupes successifs dans le parenthésées modèle. **signifie tous les répertoires (sous) *, récursivement. La finale (/)n'est pas un groupe entre parenthèses mais un qualificatif glob qui signifie ne correspondre qu'aux répertoires. ${2:l}convertit $2en minuscules.

Portable

À un niveau:

for x in root/*/; do mv -i "$x" "$(printf %s "$x" | tr '[:upper:]' '[:lower:]')"; done

La finale /limite la correspondance aux répertoires et lui mv -ifait demander une confirmation en cas de collision. Retirez le -ipour écraser en cas de collision et utilisez yes n | for …. pour ne pas être invité et ne pas effectuer de changement de nom qui entrerait en collision.

Récursivement:

find root/* -depth -type d -exec sh -c '
    t=${0%/*}/$(printf %s "${0##*/}" | tr "[:upper:]" "[:lower:]");
    [ "$t" = "$0" ] || mv -i "$0" "$t"
' {} \;

L'utilisation de -depthassure que les répertoires profondément imbriqués sont traités avant leurs ancêtres. Le traitement du nom repose sur l'existence d'un /; si vous voulez appeler operer dans le répertoire courant, utilisez ./*(l'adaptation du script shell pour faire face .ou *est laissé comme exercice pour le lecteur).

Renommer Perl

Ici, j'utilise le script de changement de nom Perl /usr/bin/prenamefourni par Debian et Ubuntu (généralement également disponible rename). À un niveau:

rename 's!/([^/]*/?)$!\L/$1!' root/*/

Récursivement, avec bash ≥4 ou zsh:

shopt -s globstar  # only in bash
rename 's!/([^/]*/?)$!\L/$1!' root/**/*/

De manière récursive, portable:

find root -depth -type d -exec rename -n 's!/([^/]*/?)$!\L/$1!' {} +

Au moins sous OS X, cela échouera si des répertoires sont déjà en minuscules: mv -i a adonnez "mv: rename a à a / a: Argument invalide".
Janus

@Janus: D'accord, vous obtenez un message d'erreur, qui est moche (bien qu'inoffensif en ligne de commande). Mais de toute façon, j'aurais dû utiliser zmv, qui s'occupe de ce cas.
Gilles 'SO- arrête d'être méchant'

J'ai ensuite trouvé -execdirce qui est génial: unix.stackexchange.com/questions/5412/… J'ai ensuite trouvé qu'il y avait de la PATHfolie et était triste :-(
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

4

Il n'y a pas une seule commande qui fera cela, mais vous pouvez faire quelque chose comme ceci:

for fd in */; do
  #get lower case version
  fd_lower=$(printf %s "$fd" | tr A-Z a-z)
  #if it wasn't already lowercase, move it.
  [ "$fd" != "$fd_lower" ] && mv "$fd" "$fd_lower"
done

Si vous en avez besoin pour être robuste, vous devez tenir compte du fait qu'il existe déjà deux répertoires qui ne diffèrent qu'en cas.

En une ligne:

for fd in */; do fd_lower=$(printf %s "$fd" | tr A-Z a-z) && [ "$fd" != "$fd_lower" ] && mv "$fd" "$fd_lower"; done

Cela est apparu au milieu de mon écriture la suggestion (essentiellement la même):for file in * ; do if [ -d "$file" ] ; then dest="$(echo $file | sed y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/)" ; [ "$dest" != "$file" ] && mv "$file" "$dest" ; fi ; done
frabjous

J'essayais de trouver une solution find -type d, mais je n'arrivais pas à comprendre
Michael Mrozek

1
Mon instinct aurait été de faire for fd in */;, évitant ainsi la nécessité de vérifier s'il s'agissait d'un répertoire, mais je n'ai aucune idée si cet instinct était bon.
Steven D

Oui, pour ... * / serait mieux.
Shawn J. Goff

1
@Shawn: trattend déjà une gamme, donc tr '[A-Z]' '[a-z]'traduit [à [et ]à ]en passant. C'est inutile mais inoffensif; cependant, sans les guillemets, le shell étendrait les crochets s'il y avait un fichier avec un nom à une lettre majuscule dans le répertoire courant.
Gilles 'SO- arrête d'être méchant'

0

J'ai pris cela comme un défi à une ligne :) Commencez par établir un scénario de test:

$ for d in foo Bar eVe; do mkdir -p dcthis/$d; touch dcthis/a${d}.txt; done
$ ls dcthis/
Bar     aBar.txt    aeVe.txt    afoo.txt    eVe     foo

J'utilise findpour repérer les répertoires avec des lettres majuscules, puis les télécharger via . Je suppose que l'utilisation est un peu hack-ish, mais ma tête explose toujours lorsque j'essaie d'échapper aux choses directement.sh -c 'mv {} echo {} | tr [:upper:] [:lower:]'sh -cfind

$ (cd dcthis && find . -maxdepth 1 -type d -path '*[A-Z]*' -exec sh -c 'mv {} `echo {} | tr [:upper:] [:lower:]`' \;)
$ ls dcthis/
aBar.txt    aeVe.txt    afoo.txt    bar     eve     foo

Attention: cette solution ne vérifie pas si la rétrogradation entraîne des collisions!


la vérification des collisions est facile: mv -i. Un problème plus important est que vous n'avez pas utilisé de guillemets appropriés, donc votre commande échouera s'il y a des caractères spéciaux (espaces ou \[*?) n'importe où dans le nom. Il n'y a aucun intérêt à l'utiliser à findmoins que ce ne soit récursif, et alors vous en avez besoin find -depthet -pathdevez l'être -name. Voir ma réponse pour des exemples de travail.
Gilles 'SO- arrête d'être méchant'

@Giles. Merci! Je vous ai vu mv -iaprès avoir écrit ceci. Bon point avec la citation ...
Janus

0

find -execdir| Renommer

Ce serait la meilleure façon de le faire sans la folie relative du chemin, car cela évite que Perl regex fu n'agisse que sur le nom de base:

PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
  find a -depth -execdir rename 's/(.*)/\L$1/' '{}' \;

-execdird'abord cddans le répertoire avant d'exécuter uniquement sur le nom de base.

Malheureusement, je ne peux pas me débarrasser de cette PATHpartie de piratage, find -execdirrefuse de faire quoi que ce soit si vous avez un chemin relatif dans PATH: /ubuntu/621132/why-using-the-execdir-action- is-insecure-for-directory-which-is-in-the-path / 1109378 # 1109378

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.