1
votes

Renommez les répertoires de manière récursive de la caisse pascal ou camel à la caisse kebab

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.

  1. Il fonctionne à la fois sur les fichiers et les répertoires. Je souhaite renommer uniquement les répertoires
  2. Il ne boucle pas de manière récursive.
  3. Si le nom du fichier kebab case est déjà là, il dit 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


2 commentaires

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 / ^ - // '


3 Réponses :


1
votes

zsh:

autoload -Uz zmv

zmv -n -Q '**/|*[[:upper:]]*(/od)' \
'${(M)f##*/}${(L)${${f##*/}//(#b)([[:upper:]])/-$match[1]}#-}'

supprimer -n si la sortie est correcte.


4 commentaires

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.



1
votes

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


4 commentaires

@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



1
votes

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' _ {} +


1 commentaires

s / \ (. \) \ ([[: upper:]] \) / \ 1- \ 2 / g ne gérera pas correctement les lettres majuscules répétées.