我必须递归地重命名一个完整的文件夹树,这样就不会出现大写字母(这是c++源代码,但这无关紧要)。

忽略CVS和Subversion版本控制文件/文件夹的加分项。首选的方法是shell脚本,因为shell应该在任何Linux机器上可用。

关于文件重命名的细节有一些有效的争论。

I think files with the same lowercase names should be overwritten; it's the user's problem. When checked out on a case-ignoring file system, it would overwrite the first one with the latter, too. I would consider A-Z characters and transform them to a-z, everything else is just calling for problems (at least with source code). The script would be needed to run a build on a Linux system, so I think changes to CVS or Subversion version control files should be omitted. After all, it's just a scratch checkout. Maybe an "export" is more appropriate.


当前回答

我在Mac OS X上发现的最简单的方法是使用http://plasmasturm.org/code/rename/:上的重命名包

brew install rename
rename --force --lower-case --nows *

——force即使目标文件名已经存在,也要重命名。 ——lower-case将文件名全部转换为小写。 替换文件名中所有空格序列为单个下划线字符。

其他回答

最初的问题要求忽略SVN和CVS目录,这可以通过在find命令中添加-prune来实现。例如忽略CVS:

find . -name CVS -prune -o -exec mv '{}' `echo {} | tr '[A-Z]' '[a-z]'` \; -print

[编辑]我尝试了一下,在find中嵌入小写翻译并没有起作用,原因我实际上不明白。因此,将其修改为:

$> cat > tolower
#!/bin/bash
mv $1 `echo $1 | tr '[:upper:]' '[:lower:]'`
^D
$> chmod u+x tolower 
$> find . -name CVS -prune -o -exec tolower '{}'  \;

Ian

使用排版:

typeset -l new        # Always lowercase
find $topPoint |      # Not using xargs to make this more readable
  while read old
  do new="$old"       # $new is a lowercase version of $old
     mv "$old" "$new" # Quotes for those annoying embedded spaces
  done

在Windows上,像Git Bash这样的模拟可能会失败,因为Windows在本质上不区分大小写。对于这些,添加一个步骤,mv的文件首先到另一个名称,如“$old.tmp”,然后到$new。

在OS X中,mv -f显示“same file”错误,所以我重命名两次:

for i in `find . -name "*" -type f |grep -e "[A-Z]"`; do j=`echo $i | tr '[A-Z]' '[a-z]' | sed s/\-1$//`; mv $i $i-1; mv $i-1 $j; done

冗长但“没有惊喜和装置的作品”

This script handles filenames with spaces, quotes, other unusual characters and Unicode, works on case insensitive filesystems and most Unix-y environments that have bash and awk installed (i.e. almost all). It also reports collisions if any (leaving the filename in uppercase) and of course renames both files & directories and works recursively. Finally it's highly adaptable: you can tweak the find command to target the files/dirs you wish and you can tweak awk to do other name manipulations. Note that by "handles Unicode" I mean that it will indeed convert their case (not ignore them like answers that use tr).

# adapt the following command _IF_ you want to deal with specific files/dirs
find . -depth -mindepth 1 -exec bash -c '
  for file do
    # adapt the awk command if you wish to rename to something other than lowercase
    newname=$(dirname "$file")/$(basename "$file" | awk "{print tolower(\$0)}")
    if [ "$file" != "$newname" ] ; then
        # the extra step with the temp filename is for case-insensitive filesystems
        if [ ! -e "$newname" ] && [ ! -e "$newname.lcrnm.tmp" ] ; then
           mv -T "$file" "$newname.lcrnm.tmp" && mv -T "$newname.lcrnm.tmp" "$newname" 
        else
           echo "ERROR: Name already exists: $newname"
        fi
    fi    
  done
' sh {} +

参考文献

我的剧本是基于以下这些精彩的回答:

https://unix.stackexchange.com/questions/9496/looping-through-files-with-spaces-in-the-names

如何在Bash中转换字符串为小写?

for f in `find -depth`; do mv ${f} ${f,,} ; done

Find -depth打印每个文件和目录,目录的内容在目录本身之前打印。${f,,}将文件名小写。