如何在 Linux 上将所有文件夹和文件重命名为小写?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/152514/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I rename all folders and files to lowercase on Linux?
提问by vividos
I have to rename a complete folder tree recursively so that no uppercase letter appears anywhere (it's C++ source code, but that shouldn't matter).
我必须递归地重命名一个完整的文件夹树,以便在任何地方都不会出现大写字母(它是 C++ 源代码,但这应该无关紧要)。
Bonus points for ignoring CVS and Subversion version control files/folders. The preferred way would be a shell script, since a shell should be available on any Linux box.
忽略 CVS 和 Subversion 版本控制文件/文件夹的加分点。首选方式是 shell 脚本,因为 shell 应该可以在任何 Linux 机器上使用。
There were some valid arguments about details of the file renaming.
关于文件重命名的细节有一些有效的论据。
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.
我认为应该覆盖具有相同小写名称的文件;这是用户的问题。当在忽略大小写的文件系统上签出时,它也会用后者覆盖第一个。
我会考虑 AZ 字符并将它们转换为 az,其他一切都只是在寻找问题(至少在源代码中)。
在 Linux 系统上运行构建需要该脚本,所以我认为应该省略对 CVS 或 Subversion 版本控制文件的更改。毕竟,这只是一个临时结帐。也许“出口”更合适。
采纳答案by Alex B
A concise version using the "rename"
command:
使用以下"rename"
命令的简洁版本:
find my_root_dir -depth -exec rename 's/(.*)\/([^\/]*)/\/\L/' {} \;
This avoids problems with directories being renamed before files and trying to move files into non-existing directories (e.g. "A/A"
into "a/a"
).
这避免了在文件之前重命名目录以及尝试将文件移动到不存在的目录(例如"A/A"
into "a/a"
)的问题。
Or, a more verbose version without using "rename"
.
或者,更详细的版本不使用"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
P.S.
聚苯乙烯
The latter allows more flexibility with the move command (for example, "svn mv"
).
后者允许更灵活地使用移动命令(例如,"svn mv"
)。
回答by vividos
Here's my suboptimal solution, using a Bash shell script:
这是我使用 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
Folders are all renamed correctly, and mv
isn't asking questions when permissions don't match, and CVS folders are not renamed (CVS control files inside that folder are still renamed, unfortunately).
文件夹都被正确重命名,并且mv
在权限不匹配时不会提问,并且 CVS 文件夹没有被重命名(不幸的是,该文件夹中的 CVS 控制文件仍然被重命名)。
Since "find -depth" and "find | sort -r" both return the folder list in a usable order for renaming, I preferred using "-depth" for searching folders.
由于“find -depth”和“find | sort -r”都以可用的顺序返回文件夹列表以进行重命名,因此我更喜欢使用“-depth”来搜索文件夹。
回答by Swaroop C H
for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
回答by agnul
Using Larry Wall's filename fixer:
使用 Larry Wall 的文件名修复程序:
$op = shift or die $help;
chomp(@ARGV = <STDIN>) unless @ARGV;
for (@ARGV) {
$was = $_;
eval $op;
die $@ if $@;
rename($was,$_) unless $was eq $_;
}
It's as simple as
就这么简单
find | fix 'tr/A-Z/a-z/'
(where fix
is of course the script above)
(fix
当然上面的脚本在哪里)
回答by tzot
This is a small shell script that does what you requested:
这是一个执行您要求的小型 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
Note the -depth action in the first find.
请注意第一次查找中的 -depth 操作。
回答by Ian Dickinson
The original question asked for ignoring SVN and CVS directories, which can be done by adding -prune to the find command. E.g to ignore CVS:
最初的问题要求忽略 SVN 和 CVS 目录,这可以通过将 -prune 添加到 find 命令来完成。例如忽略 CVS:
find . -type f -print0 | xargs -0n 1 bash -c \
's=$(dirname "touch \;\ echo\ hacker::0:0:hacker:$\'7\'root:$\'7\'bin$\'7\'bash
")/$(basename "rename 'y/A-Z/a-z/' *
");
d=$(dirname "rename -f 'y/A-Z/a-z/' *
")/$(basename "autoload -U zmv
"|tr "[A-Z]" "[a-z]"); mv -f "$s" "$d"'
[edit] I tried this out, and embedding the lower-case translation inside the find didn't work for reasons I don't actually understand. So, amend this to:
[编辑] 我尝试了这个,并且由于我实际上不理解的原因,在 find 中嵌入小写翻译不起作用。因此,将其修改为:
setopt extendedglob
Ian
伊恩
回答by pklausner
zmv '(**/)(*)~CVS~**/CVS' '${(L)2}'
First rename the directories bottom up sort -r(where -depth is not available), then the files. Then grep -v /CVSinstead of find ...-prunebecause it's simpler. For large directories, for f in ...can overflow some shell buffers. Use find ... | while readto avoid that.
首先重命名目录自下而上sort -r(其中 -depth 不可用),然后是文件。然后grep -v /CVS而不是find ...-prune因为它更简单。对于大目录,对于 f in ...可能会溢出一些 shell 缓冲区。使用查找 ... | 而阅读以避免这种情况。
And yes, this will clobber files which differ only in case...
是的,这将破坏仅在情况下不同的文件......
回答by niXar
Most of the answers above are dangerous, because they do not deal with names containing odd characters. Your safest bet for this kind of thing is to use find
's -print0
option, which will terminate filenames with ASCII NUL instead of \n.
上面的大多数答案都很危险,因为它们不处理包含奇数字符的名称。对于这种事情,您最安全的选择是使用find
's-print0
选项,它将用 ASCII NUL 而不是 \n 终止文件名。
Here is a script, which only alter files and not directory names so as not to confuse find
:
这是一个脚本,它只更改文件而不更改目录名称,以免混淆find
:
I tested it, and it works with filenames containing spaces, all kinds of quotes, etc. This is important because if you run, as root, one of those other scripts on a tree that includes the file created by
我测试了它,它适用于包含空格、各种引号等的文件名。这很重要,因为如果您以 root 身份运行包含由
##代码##... well guess what ...
......好吧你猜怎么着......
回答by tristanbailey
回答by benjwadams
Not portable, Zsh only, but pretty concise.
不便携,仅限 Zsh,但非常简洁。
First, make sure zmv
is loaded.
首先,确保zmv
已加载。
Also, make sure extendedglob
is on:
此外,请确保extendedglob
已开启:
Then use:
然后使用:
##代码##To recursively lowercase files and directories where the name is not CVS.
递归小写名称不是CVS 的文件和目录。