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 -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
请注意:此解决方案不检查外壳是否会导致碰撞!
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:无效的参数”。