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

linux rename lowercase directory-traversal

173135 观看

26回复

3189 作者的声誉

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

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

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

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

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

作者: vividos 的来源 发布者: 2008 年 9 月 30 日

回应 (26)


4

3189 作者的声誉

这是我的次优解决方案,使用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”来搜索文件夹。

作者: vividos 发布者: 30.09.2008 10:27

79

10544 作者的声誉

for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
作者: Swaroop C H 发布者: 30.09.2008 10:36

4

6196 作者的声誉

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

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

作者: agnul 发布者: 30.09.2008 10:50

3

64239 作者的声誉

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

作者: tzot 发布者: 30.09.2008 10:54

2

44695 作者的声誉

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

  1. 如果你有在路径分级仅由大小写不同的同级别两个或两个以上的名字,如要发生什么ABCdefabcDEFaBcDeF?重命名脚本应该中止还是只是警告并继续?

  2. 如何为非US-ASCII名称定义小写?如果可能存在此类名称,是否应首先执行检查和排除传递?

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

作者: Mihai Limbășan 发布者: 30.09.2008 10:57

4

10120 作者的声誉

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

find . -name CVS -prune -o -exec mv '{}' `echo {} | tr '[A-Z]' '[a-z]'` \; -print

[编辑]我尝试了这一点,并在查找中嵌入小写翻译不起作用,我实际上并不理解。所以,修改为:

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

伊恩

作者: Ian Dickinson 发布者: 30.09.2008 11:08

0

129 作者的声誉

( 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而不是找到...-修剪因为它更简单。对于大型目录,对于f in ...可以溢出一些shell缓冲区。使用find ... | 阅读时要避免这种情况。

是的,这将是clobber文件,只有在案件中有所不同...

作者: pklausner 发布者: 30.09.2008 11:26

158

57596 作者的声誉

决定

使用"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

PS

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

作者: Alex B 发布者: 30.09.2008 12:03

14

625 作者的声誉

上面的大多数答案都很危险,因为它们不处理包含奇数字符的名称。对于这类事情,你最安全的选择是使用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"'

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

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

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

作者: niXar 发布者: 30.09.2008 12:34

231

3129 作者的声誉

更小仍然我很喜欢

rename 'y/A-Z/a-z/' *

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

rename -f 'y/A-Z/a-z/' *
作者: tristanbailey 发布者: 17.11.2011 12:30

1

879 作者的声誉

不便携,仅限Zsh,但非常简洁。

首先,确保zmv已加载。

autoload -U zmv

另外,确保extendedglob打开:

setopt extendedglob

然后使用:

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

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

作者: benjwadams 发布者: 18.07.2013 05:16

61

804 作者的声誉

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

zip -r foo.zip foo/*
unzip -LL foo.zip
作者: Ginhing 发布者: 31.08.2014 08:38

0

1253 作者的声誉

我需要在Windows 7上的cygwin设置上执行此操作,发现我的语法错误与我尝试过的上述建议有关(尽管我可能错过了一个工作选项)但是来自ubutu论坛的直接解决方案已经解决了:-)

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

(我以前使用下划线替换空格

for f in *\ *; do mv "$f" "${f// /_}"; done
作者: jacanterbury 发布者: 15.01.2015 05:43

0

27478 作者的声誉

Slugify Rename(正则表达式)

不完全是OP所要求的,但我希望在此页面上找到的内容:

用于重命名文件的“slugify”版本,因此它们与URL类似
(即仅包括字母数字,点和短划线):

rename "s/[^a-zA-Z0-9\.]+/-/g" filename
作者: cwd 发布者: 28.02.2015 02:32

1

1167 作者的声誉

在OSX中,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
作者: Jonghee Park 发布者: 25.03.2015 06:25

12

4056 作者的声誉

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

rename --lower-case --force somedir/*
作者: alemol 发布者: 09.11.2015 09:08

1

656 作者的声誉

在这种情况下我会达到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])
作者: John Foley 发布者: 31.01.2016 06:07

1

21 作者的声誉

for f in `find -depth`; do mv ${f} ${f,,} ; done

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

作者: Chris Schierkolk 发布者: 22.02.2016 06:42

6

769 作者的声誉

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

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

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

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

作者: Pere 发布者: 01.04.2016 03:16

9

578 作者的声誉

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

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

作者: Stephen 发布者: 18.02.2017 10:54

0

822 作者的声誉

如果您使用Arch Linux,则可以renameAUR该程序包安装包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文件;)

作者: w17t 发布者: 22.06.2017 09:35

0

3214 作者的声誉

没有人建议排版?

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

在像git bash这样的Windows模拟中,这可能会失败,因为Windows在引擎盖下不区分大小写。对于那些,首先添加一个mv文件的步骤到另一个名称,如“$ old.tmp”,然后再添加到$ new。

作者: Paul Hodges 发布者: 29.09.2017 04:09

2

122 作者的声誉

使用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
作者: akilesh raj 发布者: 07.04.2018 09:32

0

1814 作者的声誉

冗长,但“没有惊喜,没有安装工作”

此脚本处理带有空格,引号,其他异常字符和Unicode的文件名,适用于不区分大小写的文件系统和大多数安装了bash和awk的Unix-y环境(即几乎所有)。它还会报告冲突(如果有的话)(将文件名保留为大写),当然也会重命名文件和目录,并以递归方式工作。最后它具有很强的适应性:你可以调整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中将字符串转换为小写?

作者: ndemou 发布者: 24.09.2018 12:12

0

26390 作者的声誉

这也适用于macOS:

ruby -e "Dir['*'].each { |p| File.rename(p, p.downcase) }"
作者: Chris 发布者: 25.12.2018 01:19

0

792 作者的声誉

find . -depth -name '*[A-Z]*'|sed -n 's/\(.*\/\)\(.*\)/mv -n -v \1\2 \1\L\2/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,但后面会列出那个。

此命令本身对于首先查找要重命名的文件特别有用。在完成重命名命令后使用此选项可搜索由于文件名冲突或错误而仍未替换的文件。


sed -n 's/\(.*\/\)\(.*\)/mv -n -v \1\2 \1\L\2/p'

此部分读取输出的文件,findmv使用正则表达式在命令中格式化它们。该-n选项停止sed打印输入,p搜索和替换正则表达式中的命令输出替换的文本。

正则表达式本身包含两个捕获:直到最后一个/(文件的目录)的部分,以及文件名本身。目录保持不变,但文件名转换为小写。所以,如果find输出./FOO/BAR,它将成为mv -n -v ./FOO/BAR ./FOO/bar。该-n选项mv可确保不会覆盖现有的小写文件。该-v选项使mv输出发生的每次更改(或者不进行./FOO/bar输出- 如果已经存在,则输出类似的内容./FOO/BAR -> ./FOO/BAR,注意没有进行任何更改)

与此一起使用find以生成将要执行的命令列表(方便地验证将在不实际执行的情况下执行的操作)


sh

这很不言自明。它将所有生成的mv命令路由到shell解释器。您可以将其替换bash为您喜欢的外壳或任何外壳。

作者: oisyn 发布者: 14.02.2019 04:29
32x32