简体   繁体   English

在ubuntu /bash下递归重命名文件和目录

[英]Rename files and directories recursively under ubuntu /bash

I want to rename all files and directories that contain the word "special" to "regular".我想将所有包含“特殊”一词的文件和目录重命名为“常规”。 It should maintain case sensitivity so "Special" won't become "regular".它应该保持区分大小写,这样“特殊”就不会变成“常规”。

How can i do this in bash recursively?我怎样才能在 bash 中递归地做到这一点?

A solution using find :使用find的解决方案:

To rename files only :重命名文件

find /your/target/path/ -type f -exec rename 's/special/regular/' '{}' \;

To rename directories only :重命名目录

find /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \+

To rename both files and directories :重命名文件和目录

find /your/target/path/ -execdir rename 's/special/regular/' '{}' \+

Try doing this (require bash --version >= 4):尝试这样做(需要bash --version >= 4):

shopt -s globstar
rename -n 's/special/regular/' **

Remove the -n switch when your tests are OK当您的测试正常时删除-n开关

警告There are other tools with the same name which may or may not be able to do this, so be careful.还有其他同名的工具可能会也可能不会这样做,所以要小心。

If you run the following command ( GNU )如果您运行以下命令 ( GNU )

$ file "$(readlink -f "$(type -p rename)")"

and you have a result like你有这样的结果

.../rename: Perl script, ASCII text executable

and not containing:并且不包含:

ELF

then this seems to be the right tool =)那么这似乎是正确的工具 =)

If not, to make it the default (usually already the case) on Debian and derivative like Ubuntu :如果没有,要使其成为Debian和衍生产品(如Ubuntu )上的默认值(通常已经是这种情况):

$ sudo update-alternatives --set rename /path/to/rename

(replace /path/to/rename to the path of your perl's rename command. (将/path/to/rename替换为perl's rename命令的路径。


If you don't have this command, search your package manager to install it ordo it manually如果您没有此命令,请搜索您的包管理器进行安装或手动安装


Last but not least, this tool was originally written by Larry Wall, the Perl's dad.最后但并非最不重要的一点是,这个工具最初是由 Perl 的父亲 Larry Wall 编写的。

If you don't mind installing another tool, then you can use rnm :如果您不介意安装其他工具,则可以使用rnm

rnm -rs '/special/regular/g' -dp -1 *

It will go through all directories/sub-directories (because of -dp -1 ) and replace special with regular in their names.它将遍历所有目录/子目录(因为-dp -1 )并用它们的名称中的常规替换special

@speakr's answer was the clue for me. @speakr 的回答是我的线索。

If using -execdir to transform both files and directories, you'll also want to remove -type f from the example shown.如果使用 -execdir 转换文件和目录,您还需要从显示的示例中删除-type f To spell it out, use:要拼写出来,请使用:

find /your/target/path/ -execdir rename 's/special/regular/' '{}' \\+

Also, consider adding g (global) flag to the regex if you want to replace all occurrences of special with regular in a given filename and not just the first occurrence.另外,如果您想在给定的文件名中用regular替换所有出现的special而不仅仅是第一次出现,请考虑将g (全局)标志添加到正则表达式。 For example:例如:

find /your/target/path/ -execdir rename 's/special/regular/g' '{}' \\+

will transform special-special.jpg to regular-regular.jpg .special-special.jpg转换为regular-regular.jpg Without the global flag, you'll end up with regular-special.jpg .如果没有全局标志,您最终会得到regular-special.jpg

FYI: GNU Rename is not installed by default on Mac OSX.仅供参考:默认情况下,Mac OSX 上未安装 GNU Rename。 If you are using the Homebrew package manager , brew install rename will remedy this.如果您使用的是Homebrew 包管理器brew install rename将解决这个问题。

As mentioned by Rui Seixas Monteiro it's best to use the -iregex pattern option with the Find command.正如 Rui Seixas Monteiro 所提到的,最好在 Find 命令中使用 -iregex 模式选项。 I've found the following works and includes the global flag in the regex as mentioned by U007D:我发现了以下作品,并在正则表达式中包含了 U007D 提到的全局标志:

Files:文件:

find /path/ -type f -iregex '.*special.*' -execdir rename 's/special/regular/g' '{}' \+;

Directories:目录:

find /path/ -type d -iregex '.*special.*' -execdir rename 's/special/regular/g' '{}' \+;

Files and Directories文件和目录

find /path/ -iregex '.*special.*' -execdir rename 's/special/regular/g' '{}' \+;

For those just wanting to rename directories you can use this command:对于那些只想重命名目录的人,您可以使用以下命令:

find /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \;

Note type is now d for directory, and using -execdir .注意类型现在是d用于目录,并使用-execdir

I haven't been able to work out how to rename both files and directories in a single pass though.不过,我一直无法弄清楚如何一次重命名文件和目录。

Someone commented earlier that once it renamed the root folder then it couldn't traverse the file tree any more.早些时候有人评论说,一旦它重命名了根文件夹,就不能再遍历文件树了。 There is a -d switch available that does a depth traversal from the bottom-up, so the root would be renamed last I believe:有一个-d开关可用,它可以从下到上进行深度遍历,因此我相信最后会重命名根:

find -d /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \;

From the manpage ( man find ):从联机帮助页( man find ):

 -d      Cause find to perform a depth-first traversal, i.e., directories are visited in post-order and all entries in a directory will be
         acted on before the directory itself.  By default, find visits directories in pre-order, i.e., before their contents.  Note, the
         default is not a breadth-first traversal.

Here is another approach which is more portable and does not rely on the rename command (since it may require different parameters depending on the distros).这是另一种更便携且不依赖于rename命令的方法(因为它可能需要不同的参数,具体取决于发行版)。

It renames files and directories recursively:它递归地重命名文件和目录:

find . -depth -name "*special*" | \
while IFS= read -r ent; do mv $ent ${ent%special*}regular${ent##*special}; done

What it does它能做什么

  • use find with -depth parameter to reorder the results by performing a depth-first traversal (ie all entries in a directory are displayed before the directory itself).使用带有-depth参数的 find 通过执行深度优先遍历来重新排序结果(即目录中的所有条目都显示在目录本身之前)。
  • do pattern substitutions to only modifiy the last occurence of regular in the path.进行模式替换以仅修改路径中最后一次出现的正则

That way the files are modified first and then each parent directory.这样,首先修改文件,然后修改每个父目录。

Example例子

Giving the following tree:给出以下树:

├── aa-special-aa
│   └── bb-special
│       ├── special-cc
│       ├── special-dd
│       └── Special-ee
└── special-00

It generate those mv commands in that particular order:它以特定顺序生成那些mv命令:

mv ./aa-special-aa/bb-special/special-cc ./aa-special-aa/bb-special/regular-cc
mv ./aa-special-aa/bb-special/special-dd ./aa-special-aa/bb-special/regular-dd
mv ./aa-special-aa/bb-special ./aa-special-aa/bb-regular
mv ./aa-special-aa ./aa-regular-aa
mv ./special-00 ./regular-00

To obtain the following tree:要获得以下树:

├── aa-regular-aa
│   └── bb-regular
│       ├── regular-cc
│       ├── regular-dd
│       └── Special-ee
└── regular-00

对于rename from util-linux 2.23.2 rename版本rename from util-linux 2.23.2以下命令对我rename from util-linux 2.23.2

find . -type f -exec rename mariadb mariadb-proxy '{}' \\;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM