Linux 在ubuntu /bash下递归重命名文件和目录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15012631/
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
Rename files and directories recursively under ubuntu /bash
提问by Tom
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 中递归地做到这一点?
采纳答案by Gilles Quenot
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 or do it manually
如果您没有此命令,请搜索您的包管理器进行安装或手动安装
Last but not least, this tool was originally written by Larry Wall, the Perl's dad.
最后但并非最不重要的一点是,这个工具最初是由 Perl 的父亲 Larry Wall 编写的。
回答by speakr
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/' '{}' \+
回答by Jahid
回答by LokMac
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.
回答by U007D
@speakr's answerwas 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. To spell it out, use:
如果使用 -execdir 转换文件和目录,您还需要-type f
从显示的示例中删除。要拼写出来,请使用:
find /your/target/path/ -execdir rename 's/special/regular/' '{}' \+
find /your/target/path/ -execdir rename 's/special/regular/' '{}' \+
Also, consider adding g
(global) flag to the regex if you want to replace alloccurrences of special
with regular
in a given filename and not just the first occurrence. For example:
此外,g
如果要替换给定文件名中所有出现的special
withregular
而不仅仅是第一次出现,请考虑向正则表达式添加(全局)标志。例如:
find /your/target/path/ -execdir rename 's/special/regular/g' '{}' \+
find /your/target/path/ -execdir rename 's/special/regular/g' '{}' \+
will transform special-special.jpg
to regular-regular.jpg
. Without the global flag, you'll end up with regular-special.jpg
.
将转换special-special.jpg
为regular-regular.jpg
. 如果没有全局标志,你最终会得到regular-special.jpg
.
FYI: GNU Rename is not installed by default on Mac OSX. If you are using the Homebrew package manager, brew install rename
will remedy this.
仅供参考:默认情况下,Mac OSX 上未安装 GNU Rename。如果您使用的是Homebrew 包管理器,brew install rename
将解决这个问题。
回答by jyvet
Here is another approach which is more portable and does notrely 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(i.e. all entries in a directory are displayed before the directory itself). - do pattern substitutions to only modifiy the last occurence of regularin the path.
- 使用带
-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
回答by rok
For rename
version rename from util-linux 2.23.2
the following command worked for me:
对于rename
版本rename from util-linux 2.23.2
,以下命令对我有用:
find . -type f -exec rename mariadb mariadb-proxy '{}' \;
find . -type f -exec rename mariadb mariadb-proxy '{}' \;
回答by Dig
As mentioned by Rui Seixas Monteiro it's best to use the -iregex pattern option with the Find command. I've found the following works and includes the global flag in the regex as mentioned by U007D:
正如 Rui Seixas Monteiro 所提到的,最好在 Find 命令中使用 -iregex 模式选项。我发现了以下作品,并在正则表达式中包含了 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' '{}' \+;