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

我必须recursion重命名一个完整的文件夹树,以便任何地方都不会出现大写字母(这是C ++源代码,但这不应该)。 奖金点忽略CVS和SVN控制文件/文件夹。 首选的方法是shell脚本,因为shell应该在任何Linux机器上都可用。

关于文件重命名的细节有一些有效的参数。

  1. 我认为具有相同小写名字的文件应该被覆盖,这是用户的问题。 在忽略文件系统的情况下检出时,也会用后者覆盖第一个文件系统。

  2. 我会考虑AZ字符并将其转换为az,其他所有内容都只是调用问题(至less在源代码中)。

  3. 脚本将需要在Linux系统上运行构build,所以我认为应该省略对CVS或SVN控制文件的更改。 毕竟,这只是一个临时结账。 也许一个“出口”是比较合适的。

使用"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 '[AZ]' '[az]'` if [ "${SRC}" != "${DST}" ] then [ ! -e "${DST}" ] && mv -T "${SRC}" "${DST}" || echo "${SRC} was not renamed" fi done 

PS

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

还小我还是挺喜欢的

 rename 'y/AZ/az/' * 

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

 rename -f 'y/AZ/az/' * 
 for f in `find`; do mv -v "$f" "`echo $f | tr '[AZ]' '[az]'`"; done 

只要简单地尝试跟随,如果你不需要关心效率。

 zip -r foo.zip foo/* unzip -LL foo.zip 

上面的大多数答案是危险的,因为它们不处理包含奇数字符的名字。 你最安全的select就是使用find的-print0选项,它会以ascii NUL而不是\ n结尾文件名。 在这里我提交这个脚本,它只改变文件而不改变目录名,以免混淆查找。

 find . -type f -print0 | xargs -0n 1 bash -c \ 's=$(dirname "$0")/$(basename "$0"); d=$(dirname "$0")/$(basename "$0"|tr "[AZ]" "[az]"); mv -f "$s" "$d"' 

我对它进行了testing,它可以处理包含空格,各种引号等的文件名。这一点很重要,因为如果以root身份运行包含由以下内容创build的文件的树上的其他脚本之一:

 touch \;\ echo\ hacker::0:0:hacker:\$\'\057\'root:\$\'\057\'bin\$\'\057\'bash 

…猜猜看是什么…

你们喜欢的人会让事情变得复杂

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

使用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/AZ/az/' 

(修复当然是上面的脚本)

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

 find . -name CVS -prune -o -exec mv '{}' `echo {} | tr '[AZ]' '[az]'` \; -print 

我尝试了这一点,并将embedded小写的翻译find没有工作的原因,我实际上不明白。 所以,修改为:

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

伊恩

这是我的次优解决scheme,使用bash Shell脚本:

 #!/bin/bash # first, rename all folders for f in `find . -depth ! -name CVS -type d`; do g=`dirname "$f"`/`basename "$f" | tr '[AZ]' '[az]'` 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 '[AZ]' '[az]'` if [ "xxx$f" != "xxx$g" ]; then echo "Renaming file $f" mv -f "$f" "$g" fi done 

编辑:我做了一些修改的基础上,迄今为止的build议。 现在所有的文件夹都被正确地重命名,当权限不匹配时,mv不会问问题,CVS文件夹也不会被重命名(不幸的是,该文件夹中的CVS控制文件仍然被重命名)。

编辑:由于“find -depth”和“find | sort -r”都以可用的重命名顺序返回文件夹列表,所以我最好使用“-depth”来search文件夹。

这是一个很小的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操作。

这适用于所有基于Unix的操作系统,包括Mac:

 rename --lower-case --force somedir/* 

这适用于CentOS / Redhat或其他发行版,不需要rename Perl脚本:

 for i in $( ls | grep [AZ] ); do mv -i "$i" "`echo $i | tr 'AZ' 'a-z'`"; done 

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

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

之前发布的版本可以完美的开箱即用,或者针对简单的情况进行一些调整,但在运行批量重命名之前,您可能需要考虑一些情况:

  1. 如果在path层次结构中的同一级别有两个或更多个名称(如ABCdefabcDEFaBcDeFabcDEF aBcDeF什么? 重命名脚本应该中止还是继续?

  2. 如何为非US-ASCII名称定义小写字母? 如果这样的名字可能存在,是否应该首先执行一个检查和排除通行证?

  3. 如果您正在CVS或SVN工作副本上运行重命名操作,则如果更改文件或目录名称上的大小写,则可能会损坏工作副本。 脚本是否也应该find并调整内部pipe理文件,如.svn / entries或CVS / Entries?

不可移植,Zsh只,但很简洁。

首先,确保zmv已加载。

 autoload -U zmv 

另外,请确保extendedglob在:

 setopt extendedglob 

然后使用:

 zmv '(**/)(*)~CVS~**/CVS' '${1}${(L)2}' 

以recursion方式小写的文件和名称不是CVS的目录。

在OSX中,mv -f显示“相同的文件”错误,所以我重命名了两次。

 for i in `find . -name "*" -type f |grep -e "[AZ]"`; do j=`echo $i | tr '[AZ]' '[az]' | sed s/\-1$//`; mv $i $i-1; mv $i-1 $j; done 
 for f in `find -depth`; do mv ${f} ${f,,} ; done 

find -depth打印每个文件和目录,并在目录本身之前打印一个目录的内容。 ${f,,}文件名称。

 ( 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 '[AZ]' '[az]'`; done 

首先重命名自上而下的目录sort -r (其中-depth不可用),然后是文件。 然后, grep -v / CVS而不是find…-修剪,因为它更简单。 对于大型目录, f in会溢出一些shell缓冲区。 使用find … | 同时阅读,以避免这一点。

是的,这将打破只有情况下不同的文件…

Slugify重命名(正则expression式)

不是什么OP要求,但我希望在这个页面上find:

重命名文件的“slugify”版本,因此它们与URL类似
(即只包括字母数字,点和破折号):

 rename "s/[^a-zA-Z0-9\.]+/-/g" filename 

我需要在Windows 7上的cygwin安装程序上执行此操作,并发现我尝试了上面的build议(虽然我可能错过了一个工作选项)的语法错误,但直接从ubutu论坛的这种解决scheme工作了jar:-)

 ls | while read upName; do loName=`echo "${upName}" | tr '[:upper:]' '[:lower:]'`; mv "$upName" "$loName"; done 

(NB我以前用下划线replace空格

 for f in *\ *; do mv "$f" "${f// /_}"; done 

我会在这种情况下达到python,以避免乐观地假设没有空格或斜杠的path。 我也发现, 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]) 

如果您使用Arch Linux ,则可以从AUR安装rename软件包,该软件包提供renamexm命令作为/usr/bin/renamexm可执行文件及其手册页。

这是快速重命名文件和目录的强大工具。

转换为小写

 rename -l Developers.mp3 # or --lowcase 

转换成UPPER的情况

 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 # substite string on pattern --yes # Confirm all actions 

如果需要,可以从这里获取示例Developers.mp3文件;)

没有人build议排版?

 typeset -l new # always lowercase find $topPoint | # not using xargs to make this more readable while read old do mv "$old" "$new" # quotes for those annoying embedded spaces done 

在Windows模拟像git bash这可能会失败,因为在引擎盖下窗口不区分大小写。 对于那些,添加一个mv的文件到另一个名字,如“$ old.tmp”,然后到$新。