我想将目录下的每个目录名称小写。我可以使用哪些命令来做到这一点?
答案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 -c
find
$ (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