如何在Linux上将所有文件夹和文件重命名为小写?

时间:2020-03-06 14:55:00  来源:igfitidea点击:

我必须递归重命名完整的文件夹树,以便任何地方都没有大写字母(这是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身份运行树上包含以下文件的其他脚本之一,则该脚本包括:

##代码##

...猜猜是什么...