Answers:
所有目录都位于一个级别,还是递归?
一方面:
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确保深度嵌套目录在其祖先之前得到处理。名称处理取决于是否存在/; 如果要在当前目录中调用operate,请使用./*(使shell脚本适应.或应付*读者的练习)。
在这里,我使用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!' {} +
没有一个命令可以执行此操作,但是您可以执行以下操作:
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
for file in * ; do if [ -d "$file" ] ; then dest="$(echo $file | sed y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/)" ; [ "$dest" != "$file" ] && mv "$file" "$dest" ; fi ; done
find -type d,但未能完全解决
for fd in */;,因此避免了检查它是否是目录的需要,但是我不知道这种本能是否很好。
tr已经预计范围,因此tr '[A-Z]' '[a-z]'转换[到[并]以]一笔带过。这是无用但无害的。但是,如果在当前目录中有一个文件名带有一个大写字母的文件,那么外壳程序将不带引号将其括起来。
我将此视为一个单线挑战:)首先,建立一个测试案例:
$ 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
请注意:此解决方案不检查外壳是否会导致碰撞!
mv -i。更大的问题是您没有使用正确的引号,因此,如果\[*?名称中的任何地方有特殊字符(空格或),则命令将失败。find除非递归使用,否则没有意义,然后您需要find -depth且-path必须是-name。请参阅我的答案以获取工作示例。
mv -i写完这本书后,我看到了你。用引号的要点...
find -execdir| 改名
如果不是因为相对路径疯狂,这将是最好的方法,因为它避免了Perl regex fu仅对基本名称起作用:
PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
find a -depth -execdir rename 's/(.*)/\L$1/' '{}' \;
-execdir首先cd进入目录,然后仅对基本名称执行。
不幸的是,如果您在...中有相对路径,我将无法摆脱该PATH黑客行为,并且find -execdir拒绝执行任何操作PATH:https : //askubuntu.com/questions/621132/why-using-the-execdir-action-目录路径不安全/ 1109378#1109378
mv -i a a给出“ mv:将a重命名为a / a:无效的参数”。