将目录下的所有目录小写

将目录下的所有目录小写

我想将目录下的每个目录名称小写。我可以使用哪些命令来做到这一点?

答案1

所有目录都处于一级,还是递归?

兹什

在一个层面上:

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

递归地:

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

说明:zmv根据给定的替换文本重命名与模式匹配的文件。将选项-o-i传递给底层的-i每个命令(见下文)。mv在替换文本中,$1$2等是模式中连续的括号组。**递归地表示所有(子)*目录。最后一个(/)不是带括号的组,而是全局限定符,意味着仅匹配目录。${2:l}转换$2为小写。

便携的

在一个层面上:

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

最后一个/将匹配限制为目录,并mv -i在发生冲突时要求确认。删除-i以便在发生碰撞时覆盖,然后使用yes n | for …。不被提示,也不执行任何可能发生冲突的重命名。

递归地:

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

使用-depth可确保深度嵌套的目录在其祖先目录之前得到处理。名称处理依赖于存在/;如果您想在当前目录中调用操作,请使用./*(调整shell脚本以应对.*留给读者作为练习)。

Perl重命名

这里我使用 Debian 和 Ubuntu 附带的 Perl 重命名脚本/usr/bin/prename(通常也可用rename)。在一个层面上:

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

递归地,使用 bash ≥4 或 zsh:

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

递归地、可移植地:

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

答案2

没有一个命令可以做到这一点,但你可以这样做:

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

如果您需要它足够强大,则应该考虑何时已经存在两个仅大小写不同的目录。

作为单行:

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

答案3

我将此视为一个简单的挑战:)首先,建立一个测试用例:

$ 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

我过去常常用find大写字母来识别目录,然后通过.我猜使用有点黑客,但当我尝试直接转义时,我的头总是爆炸。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

请注意:此解决方案不会检查大小写是否会导致冲突!

答案4

find -execdir rename

这将使用仅影响基本名称的正则表达式重命名文件和目录。

所以对于前缀你可以这样做:

PATH=/usr/bin find . -depth -execdir rename 's/(.*)/\L$1/' '{}' \;

或仅影响文件:

PATH=/usr/bin find . -type f -execdir rename 's/(.*)/\L$1/' '{}' \;

-execdir在仅对基本名称执行之前,首先cd进入目录。

我在以下位置对此进行了更详细的解释:https://stackoverflow.com/questions/16541582/find-multiple-files-and-rename-them-in-linux/54163971#54163971

相关内容