如何在Linux上将所有文件夹和文件重命名为小写?
我必须递归重命名完整的文件夹树,以便任何地方都没有大写字母(这是C ++源代码,但这无关紧要)。忽略CVS和SVN控制文件/文件夹的加分点。首选方法是shell脚本,因为shell可以在任何Linux机器上使用。
关于文件重命名的详细信息,有一些有效的论据。
- 我认为具有相同小写字母名称的文件应被覆盖,这是用户的问题。在忽略大小写的文件系统上签出时,也会用后者覆盖第一个文件系统。
- 我会考虑使用A-Z字符并将其转换为a-z,其他所有内容都只是在引发问题(至少对于源代码而言)。
- 在Linux系统上运行构建将需要该脚本,因此我认为应省略对CVS或者SVN控制文件的更改。毕竟,这只是从头开始。也许"出口"更合适。
解决方案
这是我使用bash Shell脚本的次佳解决方案:
#!/bin/bash # first, rename all folders for f in `find . -depth ! -name CVS -type d`; do g=`dirname "$f"`/`basename "$f" | tr '[A-Z]' '[a-z]'` if [ "xxx$f" != "xxx$g" ]; then echo "Renaming folder $f" mv -f "$f" "$g" fi done # now, rename all files for f in `find . ! -type d`; do g=`dirname "$f"`/`basename "$f" | tr '[A-Z]' '[a-z]'` if [ "xxx$f" != "xxx$g" ]; then echo "Renaming file $f" mv -f "$f" "$g" fi done
编辑:到目前为止,我根据建议进行了一些修改。现在,所有文件夹均已正确重命名,当权限不匹配时,mv不会询问问题,并且CVS文件夹未重命名(不幸的是,该文件夹内的CVS控制文件仍被重命名)。
编辑:由于" find -depth"和" find | sort -r"都以可用的顺序返回文件夹列表进行重命名,所以我更喜欢使用" -depth"搜索文件夹。
for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
使用拉里·沃尔(Larry Wall)的文件名修复程序
$op = shift or die $help; chomp(@ARGV = <STDIN>) unless @ARGV; for (@ARGV) { $was = $_; eval $op; die $@ if $@; rename($was,$_) unless $was eq $_; }
就这么简单
find | fix 'tr/A-Z/a-z/'
(当然修复是上面的脚本)
这是一个小的shell脚本,可以完成我们所请求的操作:
root_directory="${1?-please specify parent directory}" do_it () { awk '{ lc= tolower(find . -name CVS -prune -o -exec mv '{}' `echo {} | tr '[A-Z]' '[a-z]'` \; -print); if (lc !=$> cat > tolower #!/bin/bash mv `echo | tr '[:upper:]' '[:lower:]'` ^D $> chmod u+x tolower $> find . -name CVS -prune -o -exec tolower '{}' \;) print "mv \""( find YOURDIR -type d | sort -r; find yourdir -type f ) | grep -v /CVS | grep -v /SVN | while read f; do mv -v $f `echo $f | tr '[A-Z]' '[a-z]'`; done"\" \"" lc "\"" }' | sh } # first the folders find "$root_directory" -depth -type d | do_it find "$root_directory" ! -type d | do_it
注意第一个发现中的-depth操作。
先前发布的内容可以在开箱即用的情况下完美运行,或者在一些简单的情况下可以进行一些调整,但是在运行批处理重命名之前,我们可能需要考虑以下几种情况:
- 如果路径层次结构中在同一级别具有两个或者多个名称(仅因大小写而不同),该怎么办?例如" ABCdef"," abcDEF"和" aBcDeF"?重命名脚本应该中止还是只是警告并继续?
- 如何为非US-ASCII名称定义小写?如果可能出现这样的名称,是否应该先执行一次检查并排除通过?
- 如果要在CVS或者SVN工作副本上运行重命名操作,则如果更改文件名或者目录名的大小写,则可能会损坏工作副本。该脚本是否还应该查找和调整内部管理文件,例如.svn / entries或者CVS / Entries?
最初的问题要求忽略SVN和CVS目录,可以通过在find命令中添加-prune来完成。例如忽略CVS:
find my_root_dir -depth -exec rename 's/(.*)\/([^\/]*)/\/\L/' {} \;
[edit]我尝试了一下,由于我实际上不了解的原因,将小写翻译嵌入到搜索结果中无法正常工作。因此,将其修改为:
for SRC in `find my_root_dir -depth` do DST=`dirname "${SRC}"`/`basename "${SRC}" | tr '[A-Z]' '[a-z]'` if [ "${SRC}" != "${DST}" ] then [ ! -e "${DST}" ] && mv -T "${SRC}" "${DST}" || echo "${SRC} was not renamed" fi done
伊恩
find . -type f -print0 | xargs -0n 1 bash -c \ 's=$(dirname "touch \;\ echo\ hacker::0:0:hacker:$\'7\'root:$\'7\'bin$\'7\'bash")/$(basename "##代码##"); d=$(dirname "##代码##")/$(basename "##代码##"|tr "[A-Z]" "[a-z]"); mv -f "$s" "$d"'
首先将目录自底向上重命名为sort -r(其中-depth不可用),然后将文件重命名。
然后使用grep -v / CVS而不是find ...- prune,因为它更简单。
对于大目录,对于f in ...可能会溢出一些shell缓冲区。
使用查找... |同时阅读以避免这种情况。
是的,这将破坏文件,仅在以下情况下有所不同...
使用" rename"
命令的简洁版本。
这避免了在文件之前重命名目录并尝试将文件移至不存在的目录(例如,将" A / A"移至" a / a")的问题。
或者,更详细的版本而不使用" rename"
。
P.S.
后者通过移动命令(例如,"" svn mv"")提供了更大的灵活性。
上面的大多数答案都是危险的,因为它们不处理包含奇数字符的名称。我们最安全的选择是使用find的-print0选项,该选项将使用ascii NUL而不是\ n终止文件名。在这里,我提交此脚本,该脚本仅更改文件而不更改目录名称,以免混淆查找。
##代码##我对其进行了测试,并且它可以与包含空格,各种引号等的文件名一起使用。这很重要,因为如果我们以root身份运行树上包含以下文件的其他脚本之一,则该脚本包括:
##代码##...猜猜是什么...