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

viv*_*dos 165 linux rename lowercase

我必须递归地重命名一个完整的文件夹树,这样就不会出现任何大写字母(它是C++源代码,但这无关紧要).忽略CVS和SVN控制文件/文件夹的加分点.首选方法是shell脚本,因为shell应该可以在任何Linux机器上使用.

关于文件重命名的细节有一些有效的论据.

  1. 我认为应该覆盖具有相同小写名称的文件,这是用户的问题.当检出案例忽略文件时,系统也会用后者覆盖第一个文件系统.

  2. 我会考虑AZ字符并将它们转换为az,其他一切只是要求问题(至少使用源代码).

  3. 在Linux系统上运行构建需要脚本,因此我认为应该省略对CVS或SVN控制文件的更改.毕竟,这只是一个划痕结账.也许"出口"更合适.

tri*_*ley 247

更小仍然我很喜欢

rename 'y/A-Z/a-z/' *
Run Code Online (Sandbox Code Playgroud)

在不区分大小写的文件系统(如OS X的HFS +)上,您需要添加-f标志

rename -f 'y/A-Z/a-z/' *
Run Code Online (Sandbox Code Playgroud)

  • +1.这个确切的例子在重命名的手册页中给出. (8认同)
  • 在Arch上,该程序被称为`perl-rename`(由具有相同名称的包提供) (8认同)
  • 在 OSX 上确保您已重命名。`brew install 重命名` (5认同)
  • 这假设你有perls重命名,但并非总是如此.例如,我的debian重命名是完全不同的 (4认同)
  • http://linux.icydog.net/rename.php:`Ubuntu默认使用的重命名实用程序是Perl程序,有时称为prename. (3认同)
  • 谢谢,我就是这样用的 $ find | xargs 重命名 'y/AZ/az/' * (2认同)
  • 由于"重命名"不是递归的,因此这不能解决给定的问题. (2认同)
  • 仅供未来读者参考。这不适用于 WSL(来自 Linux 的 Windows 文件)。您会收到“文件已存在”。更多的是操作系统组合如何工作的函数。我最终做了类似``find'的事情。-深度| 重命名 -v -n -d 'y/AZ\./a-z+/'``` 后跟 ```find 。-深度| 重命名-n -v -d“s/\+/\./g”```。当然,要使这样的 hack 起作用,您需要确保没有文件名包含 +。您可以通过执行 ```find 来检查。-iname "*+*"``` (2认同)

Ale*_*x B 166

使用"rename"命令的简洁版本.

find my_root_dir -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
Run Code Online (Sandbox Code Playgroud)

这避免了在文件之前重命名目录并尝试将文件移动到不存在的目录(例如,"A/A"进入"a/a")的问题.

或者,更详细的版本没有使用"rename".

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
Run Code Online (Sandbox Code Playgroud)

PS

后者允许移动命令更灵活(例如"svn mv").

  • 使用重命名可以通过这种方式重命名'y/AZ/az /'* (31认同)
  • 对于包含空格的文件(context:linux,bash),第二种方法对我来说无法正常工作. (6认同)
  • 使用最后一个版本的重命名,不需要正则表达式.完整命令变为`find my_root_dir -depth -exec rename -c {} \;`.如果您使用不区分大小写的文件系统(例如Mac),请添加-f以重命名 (4认同)
  • 请注意,这两个版本都不适用于不区分大小写的文件系统.在我的情况下,我用'(mv"$ {SRC}""$ {DST} .renametmp"&& mv"$ {DST} .renametmp""$ {DST}")||替换`then`封闭的行.echo"$ {SRC}未重命名为"`. (2认同)

Swa*_*C H 84

for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
Run Code Online (Sandbox Code Playgroud)

  • 来自所有注释的“合并”版本(答案无法再编辑):做mv -v“ $ f”“`echo $ f | tr'[AZ]''[az]'`”; 完成``` (3认同)
  • 有人可以向我解释为什么这首先应该起作用吗?如果找到 ./FOO 和 ./FOO/BAR,它首先将 ./FOO 重命名为 ./foo,之后就找不到 ./FOO/BAR。在下面输入我自己的答案应该可以解决这个问题。 (3认同)
  • “ find”应该替换为您用来获取要重命名文件列表的任何命令;例如“ ls *。{C,CPP,H}”。 (2认同)
  • 在OS X上不起作用,仅显示`find`的使用情况信息。查找。似乎可以解决此问题。 (2认同)

Gin*_*ing 75

如果您不需要关心效率,只需尝试按照即可.

zip -r foo.zip foo/*
unzip -LL foo.zip
Run Code Online (Sandbox Code Playgroud)

  • 假设当你发现自己需要重命名目录中的文件时,计算效率通常不是问题...我认为这可能是这个线程上最具创造性的简单解决方案.实际上,这个微不足道的东西不应该像接受的答案那样复杂,而且这种解决方法与我想要在这样的操作中投入的思想量相比更加成比例.+1000 (25认同)
  • 您可以使用`-0`(即'零',无压缩)开关来加速它,`zip -0 -r foo.zip foo /`. (23认同)
  • 哇,这是一种非常低效的方式. (13认同)
  • 我不得不在不同的目录结构中更改超过50'000个文件名.原来接受的答案在2分钟内完成了不到10%的工作,其中"-0"压缩几乎是即时的! (3认同)
  • 这不仅效率低下。如果没有足够的可用空间来存储临时存档,那么这简直是“不可能”。 (2认同)
  • 我知道这是一种愚蠢且低效的方法,但它对我来说是 WSL 上最快的方法,因为 Windows 对已经存在一个大写名称的文件很生气。 (2认同)

niX*_*Xar 14

上面的大多数答案都很危险,因为它们不处理包含奇数字符的名称.对于这类事情,你最安全的选择是使用find的-print0选项,它将使用ascii NUL而不是\n来终止文件名.在这里,我提交了这个脚本,它只改变文件而不是目录名,以免混淆find.

find .  -type f -print0 | xargs -0n 1 bash -c \
's=$(dirname "$0")/$(basename "$0");
d=$(dirname "$0")/$(basename "$0"|tr "[A-Z]" "[a-z]"); mv -f "$s" "$d"'
Run Code Online (Sandbox Code Playgroud)

我测试了它,它适用于包含空格,各种引号等的文件名.这很重要,因为如果你以root身份运行树上包含由以下内容创建的文件的其他脚本之一:

touch \;\ echo\ hacker::0:0:hacker:\$\'\057\'root:\$\'\057\'bin\$\'\057\'bash
Run Code Online (Sandbox Code Playgroud)

......好吧猜猜......


Ste*_*hen 13

男人,你们喜欢复杂的事情..

重命名'y/AZ/az /'*

  • 这不起作用,它说小写名称的文件已经存在。 (3认同)

ale*_*mol 12

如果您已经拥有或设置了重命名命令(例如通过Mac中的brew安装),则此方法有效:

rename --lower-case --force somedir/*
Run Code Online (Sandbox Code Playgroud)

  • ...如果你先设置重命名,例如通过`brew install rename` (9认同)
  • 重命名'y/AZ/az /'* (3认同)
  • `--lower-case`?遗憾的是,至少在Arch Linux中并非如此. (3认同)
  • `rename`不是bash内置的.它是一个外部实用程序,语法因您安装的版本而异.这个答案不足以作为所要求的"适用于所有基于unix的OS"的便携式解决方案. (3认同)
  • 刚刚检查过,最新的 Fedora (28) 中包含的 `rename` 命令,通过 `util-linux-2.31` 包,没有 `--lower-case` 选项。 (3认同)

Kim*_*m T 11

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

brew install rename
rename --force --lower-case --nows *
Run Code Online (Sandbox Code Playgroud)

--force 重命名即使具有目标名称的文件已经存在。

--lower-case 将文件名转换为全部小写。

--nows 用单个下划线字符替换文件名中的所有空格序列。


Per*_*ere 10

这适用于没有renamePerl脚本的CentOS/Redhat或其他发行版:

for i in $( ls | grep [A-Z] ); do mv -i "$i" "`echo $i | tr 'A-Z' 'a-z'`"; done
Run Code Online (Sandbox Code Playgroud)

来源:https://linuxconfig.org/rename-all-files-from-uppercase-to-lowercase-characters

(在某些发行版中,默认rename命令来自util-linux,这是一个不同的,不兼容的工具)


Edu*_*rdo 6

单线:

for F in K*; do NEWNAME=$(echo "$F" | tr '[:upper:]' '[:lower:]'); mv "$F" "$NEWNAME"; done
Run Code Online (Sandbox Code Playgroud)

甚至:

for F in K*; do mv "$F" "${F,,}"; done
Run Code Online (Sandbox Code Playgroud)

请注意,这只会转换以字母 K 开头的文件/目录,因此请进行相应调整。


viv*_*dos 5

这是我使用 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
Run Code Online (Sandbox Code Playgroud)

文件夹都被正确重命名,并且mv在权限不匹配时不会提问,并且 CVS 文件夹没有被重命名(不幸的是,该文件夹中的 CVS 控制文件仍然被重命名)。

由于“find -depth”和“find | sort -r”都以可用的顺序返回文件夹列表以进行重命名,因此我更喜欢使用“-depth”来搜索文件夹。


agn*_*nul 5

使用 Larry Wall 的文件名修复器:

$op = shift or die $help;
chomp(@ARGV = <STDIN>) unless @ARGV;
for (@ARGV) {
    $was = $_;
    eval $op;
    die $@ if $@;
    rename($was,$_) unless $was eq $_;
}
Run Code Online (Sandbox Code Playgroud)

这很简单

find | fix 'tr/A-Z/a-z/'
Run Code Online (Sandbox Code Playgroud)

fix当然上面的脚本在哪里)


Ian*_*son 5

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

find . -name CVS -prune -o -exec mv '{}' `echo {} | tr '[A-Z]' '[a-z]'` \; -print
Run Code Online (Sandbox Code Playgroud)

[编辑]我尝试了这个,并且由于我实际上不明白的原因,在查找中嵌入小写翻译不起作用。因此,将其修改为:

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

伊恩


ben*_*ams 5

不可移植,仅限 Zsh,但非常简洁。

首先,确保zmv已加载。

autoload -U zmv
Run Code Online (Sandbox Code Playgroud)

另外,请确保extendedglob已打开:

setopt extendedglob
Run Code Online (Sandbox Code Playgroud)

然后使用:

zmv '(**/)(*)~CVS~**/CVS' '${1}${(L)2}'
Run Code Online (Sandbox Code Playgroud)

递归地小写名称不是CVS 的文件和目录。


Chr*_*ris 5

这在 macOS 上也能很好地工作:

ruby -e "Dir['*'].each { |p| File.rename(p, p.downcase) }"
Run Code Online (Sandbox Code Playgroud)