首页 > 解决方案 > 将目录从pascal或camel case递归重命名为kebab case

问题描述

如果我可以只使用重命名命令,那将是最好的。但我认为我们必须使用两个正则表达式。

正在工作的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. 它不会递归循环。
  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

标签: bashzsh

解决方案


zsh:

autoload -Uz zmv

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

-n如果输出正确则删除。


推荐阅读