如何在 Linux 上将所有文件夹和文件重命名为小写?
- 2024-10-18 09:00:00
- admin 原创
- 73
问题描述:
我必须递归地重命名完整的文件夹树,以便任何地方都不会出现大写字母(这是 C++ 源代码,但这并不重要)。
忽略 CVS 和 Subversion 版本控制文件/文件夹可获得加分。首选方式是使用 shell 脚本,因为任何 Linux 机器上都应该有 shell。
关于文件重命名的细节有一些有效的论据。
我认为具有相同小写名称的文件应该被覆盖;这是用户的问题。当在忽略大小写的文件系统上签出时,它也会用后者覆盖第一个。
我会考虑 AZ 字符并将它们转换为 az,其他一切都只是在引发问题(至少对于源代码而言)。
该脚本需要在 Linux 系统上运行构建,因此我认为应该省略对 CVS 或 Subversion 版本控制文件的更改。毕竟,这只是临时签出。也许“导出”更合适。
解决方案 1:
我还是比较喜欢小一点的:
rename 'y/A-Z/a-z/' *
在不区分大小写的文件系统(例如 OS X 的HFS+ )上,您需要添加-f
标志:
rename -f 'y/A-Z/a-z/' *
解决方案 2:
使用以下命令的简洁版本"rename"
:
find my_root_dir -depth -exec rename 's/(.*)/([^/]*)/$1/L$2/' {} ;
这避免了目录在文件之前重命名以及尝试将文件移动到不存在的目录(例如)的"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
附言
后者允许移动命令具有更大的灵活性(例如"svn mv"
)。
解决方案 3:
如果您不需要关心效率,请简单尝试以下步骤。
zip -r foo.zip foo/*
unzip -LL foo.zip
解决方案 4:
for f in `find .`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
注意:点是 macOS 兼容性所必需的,但它仍然适用于 Linux。
解决方案 5:
可以简单地使用以下不太复杂的方法:
rename 'y/A-Z/a-z/' *
解决方案 6:
我在 Mac OS X 上发现的最简单的方法是使用来自http://plasmasturm.org/code/rename/的重命名包:
brew install rename
rename --force --lower-case --nows *
--force 即使目标名称的文件已经存在,也要重命名。
--lower-case 将文件名全部转换为小写。
--nows 将文件名中的所有空格序列替换为单个下划线字符。
解决方案 7:
这适用于CentOS / Red Hat Linux或其他没有rename
Perl 脚本的发行版:
for i in $( ls | grep [A-Z] ); do mv -i "$i" "`echo $i | tr 'A-Z' 'a-z'`"; done
来源:将所有文件名从大写字符重命名为小写字符
(在某些发行版中,默认rename
命令来自 util-linux,这是一个不同的、不兼容的工具。)
解决方案 8:
如果您已经拥有或设置了重命名命令(例如通过Mac 中的brew install ),则此方法有效:
rename --lower-case --force somedir/*
解决方案 9:
上面的大多数答案都很危险,因为它们不处理包含奇数字符的名称。对于这种情况,最安全的做法是使用find
选项-print0
,它将使用 ASCII NUL 而不是 \n 来终止文件名。
这是一个脚本,它只改变文件名称而不改变目录名称,以免混淆find
:
find . -type f -print0 | xargs -0n 1 bash -c \n's=$(dirname "$0")/$(basename "$0");
d=$(dirname "$0")/$(basename "$0"|tr "[A-Z]" "[a-z]"); mv -f "$s" "$d"'
我测试过,它可以处理包含空格、各种引号等的文件名。这很重要,因为如果你以 root 身份运行包含由
touch ; echo hacker::0:0:hacker:$\'/\'root:$\'/\'bin$\'/\'bash
... 猜猜看...
解决方案 10:
不可移植,仅适用于 Zsh,但非常简洁。
首先,确保zmv
已加载。
autoload -U zmv
另外,请确保extendedglob
已打开:
setopt extendedglob
然后使用:
zmv '(**/)(*)~CVS~**/CVS' '${1}${(L)2}'
以递归方式将名称不是CVS 的文件和目录小写。
解决方案 11:
以下是我的次优解决方案,使用 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”来搜索文件夹。
解决方案 12:
单行:
for F in K*; do NEWNAME=$(echo "$F" | tr '[:upper:]' '[:lower:]'); mv "$F" "$NEWNAME"; done
甚至:
for F in K*; do mv "$F" "${F,,}"; done
请注意,这只会转换以字母 K 开头的文件/目录,因此请进行相应调整。
解决方案 13:
最初的问题要求忽略 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 '{}' ;
伊恩
解决方案 14:
for f in `find -depth`; do mv ${f} ${f,,} ; done
find -depth
打印每个文件和目录,在目录本身之前打印目录的内容。${f,,}
将文件名小写。
解决方案 15:
这在 macOS 上也能很好地运行:
ruby -e "Dir['*'].each { |p| File.rename(p, p.downcase) }"
解决方案 16:
使用 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/'
(fix
当然上面的脚本在哪里)
解决方案 17:
这是一个小型的 shell 脚本,可以执行您所要求的操作:
root_directory="${1?-please specify parent directory}"
do_it () {
awk '{ lc= tolower($0); if (lc != $0) print "mv \"" $0 "\" \"" lc "\"" }' | sh
}
# first the folders
find "$root_directory" -depth -type d | do_it
find "$root_directory" ! -type d | do_it
请注意第一个查找中的 -depth 操作。
解决方案 18:
使用排版:
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
。
解决方案 19:
以下脚本适用于基于 RedHat 的系统,例如 RHEL、CentOS、Rocky 和 Alma。
这里的所有解决方案都不适合我,因为我的系统无法访问 Perlrename
脚本,而且我想要重命名的某些文件名包含空格(这在某些答案上存在问题)。但是,我找到了一种可行的变体:
find . -depth -exec sh -c '
t=${0%/*}/$(printf %s "${0##*/}" | tr "[:upper:]" "[:lower:]");
[ "$t" = "$0" ] || mv -i "$0" "$t"
' {} ;
感谢@“Gilles 'SO- stop being evil'”,在 Unix & Linux StackExchange 上查看类似问题将整个目录树更改为小写名称中的答案。
解决方案 20:
使用 MacOS,
安装rename
软件包,
brew install rename
使用,
find . -iname "*.py" -type f | xargs -I% rename -c -f "%"
此命令查找所有带有扩展名的文件*.py
并将文件名转换为小写。
`f` - forces a rename
例如,
$ find . -iname "*.py" -type f
./sample/Sample_File.py
./sample_file.py
$ find . -iname "*.py" -type f | xargs -I% rename -c -f "%"
$ find . -iname "*.py" -type f
./sample/sample_file.py
./sample_file.py
解决方案 21:
冗长但“无意外,无安装”
该脚本处理带有空格、引号、其他不常见字符和 Unicode 的文件名,适用于不区分大小写的文件系统和安装了 bash 和 awk 的大多数 Unix 环境(即几乎所有环境)。它还会报告任何冲突(将文件名保留为大写),当然还会重命名文件和目录并递归工作。最后,它具有高度的适应性:您可以调整 find 命令以定位您想要的文件/目录,并且可以调整 awk 以执行其他名称操作。请注意,我说的“处理 Unicode”是指它确实会转换它们的大小写(而不是像使用 的答案那样忽略它们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 中将字符串转换为小写?
解决方案 22:
Slugify 重命名(正则表达式)
这并不是 OP 所要求的,但我希望在此页面上找到:
用于重命名文件的“slugify”版本,使其类似于 URL(即仅包含字母数字、点和破折号):
rename "s/[^a-zA-Z0-9.]+/-/g" filename
解决方案 23:
在 OS X 中,mv -f
显示“相同文件”错误,因此我重命名两次:
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
解决方案 24:
在这种情况下,我会使用 Python,以避免乐观地假设路径没有空格或斜杠。我还发现python2
往往比 安装在更多的地方rename
。
#!/usr/bin/env python2
import sys, os
def rename_dir(directory):
print('DEBUG: rename('+directory+')')
# Rename current directory if needed
os.rename(directory, directory.lower())
directory = directory.lower()
# Rename children
for fn in os.listdir(directory):
path = os.path.join(directory, fn)
os.rename(path, path.lower())
path = path.lower()
# Rename children within, if this child is a directory
if os.path.isdir(path):
rename_dir(path)
# Run program, using the first argument passed to this Python script as the name of the folder
rename_dir(sys.argv[1])
解决方案 25:
如果您使用Arch Linux,则可以从中安装rename
)包,AUR
该包提供可执行renamexm
命令/usr/bin/renamexm
以及随附的手册页。
这是一个非常强大的快速重命名文件和目录的工具。
转换为小写
rename -l Developers.mp3 # or --lowcase
转换为大写
rename -u developers.mp3 # or --upcase, long option
其他选择
-R --recursive # directory and its children
-t --test # Dry run, output but don't rename
-o --owner # Change file owner as well to user specified
-v --verbose # Output what file is renamed and its new name
-s/str/str2 # Substitute string on pattern
--yes # Confirm all actions
如果需要,您可以从这里获取示例Developers.mp3文件;)
解决方案 26:
使用 bash,无需rename
:
find . -exec bash -c 'mv $0 ${0,,}' {} ;
解决方案 27:
第一步
在 MacOS 上:
brew install rename
在Linux上:
sudo install rename
第二步
find . -depth -execdir rename -f 'y/A-Z/a-z/' {} ;
解释
find . -depth
:确保以深度优先的方式处理目录。在重命名父目录之前重命名子目录时,避免出现问题非常重要。
$ tree -L 3
.
└── ACB
├── HUS
└── TEXT.AA
$ find .
.
./ACB
./ACB/TEXT.AA
./ACB/HUS
$ find . -depth
./ACB/TEXT.AA
./ACB/HUS
./ACB
.
-execdir rename 'y/A-Z/a-z/' {} ;
:使用 Perl 表达式“y/AZ/az/”执行重命名命令。{}
是目录名称的占位符,;
标记选项的结束-execdir
。
$ find . -depth -execdir rename -f 'y/A-Z/a-z/' {} ;
# success
$ find .
.
./acb
./acb/text.aa
./acb/hus
解决方案 28:
( 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
首先从下往上重命名目录sort -r(其中 -depth 不可用),然后重命名文件。然后grep -v /CVS而不是find ...-prune,因为它更简单。对于大型目录,for f in ...可能会溢出某些 shell 缓冲区。使用find ... | while read可以避免这种情况。
是的,这将破坏仅大小写不同的文件......
解决方案 29:
find . -depth -name '*[A-Z]*'|sed -n 's/(.*/)(.*)/mv -n -v -T L/p'|sh
我还没有尝试过这里提到的更复杂的脚本,但是在我的 Synology NAS 上,没有一个命令行版本对我有用。rename
不可用,并且的许多变体都find
失败了,因为它似乎坚持使用已重命名路径的旧名称(例如,如果它发现./FOO
后跟./FOO/BAR
,重命名./FOO
为./foo
仍将继续列出,./FOO/BAR
即使该路径不再有效)。上面的命令对我来说没有任何问题。
以下是该命令各个部分的解释:
find . -depth -name '*[A-Z]*'
这将使用深度优先搜索(例如,它将在 之前列出)从当前目录(更改.
为要处理的任何目录)查找任何文件,但仅限于包含大写字符的文件。过滤器仅适用于基本文件名,而不是完整路径。因此这将列出但不列出。这没关系,因为我们不想重命名。我们想重命名,但那个稍后会列出(这就是为什么很重要)。./foo/bar
`./foo-name
./FOO/BAR./FOO/bar
./FOO/bar./FOO
-depth`
此命令本身对于查找您想要重命名的文件特别有用。在完成重命名命令后使用此命令可搜索由于文件名冲突或错误而尚未被替换的文件。
sed -n 's/(.*/)(.*)/mv -n -v -T L/p'
此部分读取输出的文件并使用正则表达式find
将其格式化为命令。该选项停止打印输入,搜索和替换正则表达式中的命令输出替换的文本。mv
`-nsed
p`
正则表达式本身由两个捕获组成:直到最后一个 /(即文件的目录)的部分和文件名本身。目录保持不变,但文件名将转换为小写。因此,如果find
输出./FOO/BAR
,它将变为mv -n -v -T ./FOO/BAR ./FOO/bar
。-n
选项mv
确保现有的小写文件不会被覆盖。-v
选项会mv
输出它所做的每项更改(或者不做 - 如果./FOO/bar
已经存在,它会输出类似 的内容./FOO/BAR -> ./FOO/BAR
,注意未进行任何更改)。-T
这里的 非常重要 - 它将目标文件视为目录。这将确保如果该目录恰好存在,./FOO/BAR
则不会将 移入。./FOO/bar
使用它find
来生成将要执行的命令列表(方便验证将要执行的操作而无需实际执行)
sh
这个很容易理解。它将所有生成的mv
命令路由到 shell 解释器。您可以用bash
或任何您喜欢的 shell 替换它。
解决方案 30:
我需要在 Windows 7 上的 Cygwin 设置上执行此操作,但我发现我尝试了上述建议后出现了语法错误(尽管我可能错过了一个可行的选项)。不过,这个直接来自Ubuntu 论坛的解决方案却奏效了 :-)
ls | while read upName; do loName=`echo "${upName}" | tr '[:upper:]' '[:lower:]'`; mv "$upName" "$loName"; done
(注意:我之前使用下划线替换了空格:
for f in * *; do mv "$f" "${f// /_}"; done
)
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件