【发布时间】:2011-12-30 06:01:19
【问题描述】:
我的 bash 脚本有问题... 我想以递归方式重命名所有文件、文件夹和子文件夹,从 小写到大写(反之亦然)。 我已经写了这个脚本,但是它不起作用。
find . -depth -iname \* -exec mv {} `echo {} | tr [:upper:] [:lower:]` \;
有什么建议吗? 谢谢
【问题讨论】:
标签: file bash directory renaming
我的 bash 脚本有问题... 我想以递归方式重命名所有文件、文件夹和子文件夹,从 小写到大写(反之亦然)。 我已经写了这个脚本,但是它不起作用。
find . -depth -iname \* -exec mv {} `echo {} | tr [:upper:] [:lower:]` \;
有什么建议吗? 谢谢
【问题讨论】:
标签: file bash directory renaming
为什么不使用简单的while循环:
find testdir/ -depth | while read file; do NEWNAME=$(dirname "$file")/$(echo $(basename "$file") | tr '[:lower:]' '[:upper:]'); mv "$file" "$NEWNAME"; done
【讨论】:
问题是你的反引号命令echo {} | tr [:upper:] [:lower:]首先被shell扩展,所以find实际上看到的参数是
find . -depth -iname \* -exec mv {} {} \;
(在输入 {} 上运行 tr [:upper:] [:lower:] 只会再次返回 {})。
这是一种解决方法,使用子shell 作为-exec 命令:
find . -mindepth 1 -depth -iname \* -exec \
sh -c 'mv "$0" "`tr \[:upper:\] \[:lower:\] <<<"$0"`"' {} \;
或者更易读,使用 $() 语法:
find . -mindepth 1 -depth -iname \* -exec \
sh -c 'mv "$0" "$(tr "[:upper:]" "[:lower:]" <<<$0)"' {} \;
请注意,您还需要引用 tr 字符范围以阻止 shell 扩展它们!
添加-mindepth 1 也是一个好主意,这样您在尝试运行mv . . 时就不会出错。
【讨论】:
<<< 在 bash 中创建一个“here string”,这意味着后面的任何单词都成为命令的标准输入,就像some-command <some-file 使some-file 的内容成为标准输入一样)。例如,尝试tr a-z A-Z <<<"a test string"。在这种情况下,<<<$0 将第一个参数$0 传递给sh -c ...——find 通过替换{} 传入的文件名——并将其作为tr ... 的输入。 (顺便说一句,通常脚本的第一个参数是 $1,但 sh -c 的行为不同——请参阅 Bash 手册)。