[英]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 编写的。
@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它能做什么
-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 通过执行深度优先遍历来重新排序结果(即目录中的所有条目都显示在目录本身之前)。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.