Рекурсивно переименовывать каталоги с pascal или camel case на kebab case - PullRequest
1 голос
/ 11 июля 2020

Было бы лучше, если бы я мог просто использовать команду переименования. Но я думаю, что нам нужно использовать два регулярных выражения.

Команда sed, которая работает -

% echo MyExPression | sed --expression 's/\([A-Z]\)/-\L\1/g' --expression 's/^-//'                         
my-ex-pression
% echo myExPression | sed --expression 's/\([A-Z]\)/-\L\1/g' --expression 's/^-//'
my-ex-pression

Я выяснил , что мы можем используйте

for file in ./* ; do mv "$file" "$(echo $file|sed -e 's/\([A-Z]\)/-\L\1/g' -e 's/^.\/-//')" ; done

Но эта команда имеет несколько проблем.

  1. Она работает как с файлами, так и с каталогами. Я хочу переименовать только каталоги
  2. Это не l oop рекурсивно.
  3. Если имя файла для кебаба уже есть, то в нем написано mv: cannot move './first-folder-to-rename' to a subdirectory of itself, './first-folder-to-rename/first-folder-to-rename'

Итак , что может быть здесь решением?

Обновление 1

Вот пример структуры каталогов

% tree
.
├── EmptyFile.txt
├── FirstDirectoryName
│   ├── FourthDirectoryName
│   ├── secondDirectoryName
│   └── thirdDirectoryName
├── FourthDirectoryName
├── secondDirectoryName
└── thirdDirectoryName

Ожидаемый результат

% tree
.
├── EmptyFile.txt
├── first-directory-name
│   ├── fourth-directory-name
│   ├── second-directory-name
│   └── third-directory-name
├── fourth-directory-name
├── second-directory-name
└── third-directory-name

Ответы [ 3 ]

1 голос
/ 11 июля 2020

найти + оболочку + 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 голос
/ 11 июля 2020

zsh:

autoload -Uz zmv

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

удалить -n, если вывод правильный.

0 голосов
/ 11 июля 2020

Использование bash и 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

Запуск от имени
$ ./rendirs top_of_the_directory_tree_to_be_renamed

...