Ce serait mieux si je pouvais simplement utiliser la commande renommer. Mais je pense que nous devons utiliser deux regex.
La commande sed qui fonctionne est
% tree . âââ EmptyFile.txt âââ first-directory-name â âââ fourth-directory-name â âââ second-directory-name â âââ third-directory-name âââ fourth-directory-name âââ second-directory-name âââ third-directory-name
J'ai compris que nous pouvons utiliser
% tree . âââ EmptyFile.txt âââ FirstDirectoryName â  âââ FourthDirectoryName â  âââ secondDirectoryName â  âââ thirdDirectoryName âââ FourthDirectoryName âââ secondDirectoryName âââ thirdDirectoryName
Mais cette commande a plusieurs problèmes.
mv: impossible de déplacer './first-folder-to-rename' vers un sous-répertoire de lui-même, './first-folder-to-rename/first-folder-to-rename'
li >
Alors, quelle pourrait être la solution ici?
Mise à jour 1
Voici un exemple de structure de répertoire
XXX
Résultat attendu
for file in ./* ; do mv "$file" "$(echo $file|sed -e 's/\([A-Z]\)/-\L\1/g' -e 's/^.\/-//')" ; done
3 Réponses :
zsh:
autoload -Uz zmv zmv -n -Q '**/|*[[:upper:]]*(/od)' \ '${(M)f##*/}${(L)${${f##*/}//(#b)([[:upper:]])/-$match[1]}#-}'
supprimer -n
si la sortie est correcte.
Ajustez les qualificatifs glob: (.od)
pour les fichiers simples uniquement; (od)
pour tout type. Consultez la section man zshexpn
Glob Qualifiers pour de nombreuses autres possibilités. Le tri od
est nécessaire pour que la plupart des imbriqués soient traités en premier (comme -depth
avec find
).
@blueray $ f
est le nom de fichier correspondant à zmv
. Plusieurs modifications peuvent être appliquées (car zsh peut imbriquer des extensions de paramètres). En commençant par ## * /
le plus interne pour supprimer le chemin parent (le cas échéant). Puis une substitution globale (avec backreference activée par (#b)
) pour ajouter un trait d'union avant chaque lettre majuscule. L'expansion la plus à l'extérieur réduit le résultat en minuscules et supprime le seul trait d'union. Une amélioration serait: $ {(L) $ {f ## * /} // (# b) (?) ([[: Upper:]]) / $ match [1] - $ match [2] }
. Un ## * /
distinct avec l'indicateur M
est ajouté pour correspondre à tout chemin parent existant.
(?) ([[: upper:]])
ne gère pas les lettres majuscules répétées. Par exemple. IsIBad
-> is-ibad
@blueray ** / | *
était une mauvaise idée. Utilisez (** /) (* [[: upper:]] *) (/)
et remplacez le deuxième argument par $ {1} $ {(L) $ {2 // (#b) ([[: upper:]]) / - $ match [1]} # -}
. ** /
pour la récursivité. Capturez à la fois le nom de répertoire et le nom de base comme $ 1
& $ 2
. (/)
est le seul qualificatif nécessaire car od
est déjà dans le script zmv . Désolé d'avoir publié une mauvaise réponse.
Utilisation de bash
et GNU sed
:
$ cat rendirs
#!/bin/bash # function for renaming directories recursively rendirrec () { local from to for from in *; do [[ -d $from && ! -h $from ]] || continue to=$(sed -E 's/([^A-Z])([A-Z])/\1-\2/g; s/.*/\L&/' <<< "$from") cd "$from" && { rendirrec; cd ..; } || exit [[ $to = "$from" ]] && continue if [[ -e $to ]]; then printf "'%s' already exists. Skipping..\n" "$to" >&2 continue; fi mv "$from" "$to" || exit done } [[ -z $1 ]] && { echo "Missing argument" >&2; exit 1; } cd "$1" && rendirrec
Exécuter en tant que
$ ./rendirs top_of_the_directory_tree_to_be_renamed
@blueray Il semble que ce soit corrigé maintenant. Balise bash
ajoutée.
Oui j'ai reculé.
La balise @blueray bash
a de nouveau été supprimée!
@blueray Il y avait une erreur logique dans le code. Corrigé maintenant
trouver + shell + sed + tr:
find . -depth -type d -name '*[[:upper:]]*' -exec sh -c ' for i do parent=${i%/*} [ "$parent" = "$i" ] && parent="" || parent="$parent/" newname=$(sed '\''s/\(.\)\([[:upper:]]\)/\1-\2/g'\'' <<X | tr "[:upper:]" "[:lower:]" ${i##*/} X ) echo mv -- "$i" "$parent$newname" done' _ {} +
s / \ (. \) \ ([[: upper:]] \) / \ 1- \ 2 / g
ne gérera pas correctement les lettres majuscules répétées.
Veuillez ajouter des exemples de noms de fichiers (pas de descriptions, pas d'images, pas de liens) et les noms de fichiers souhaités pour cet exemple d'entrée à votre question (pas de commentaire).
Cela pourrait aider avec GNU sed:
sed 's / [A-Z] / - \ L & / g; s / ^ - // '