ubuntu /bash 下递归重命名文件和目录
Posted
技术标签:
【中文标题】ubuntu /bash 下递归重命名文件和目录【英文标题】:Rename files and directories recursively under ubuntu /bash 【发布时间】:2013-02-07 09:20:26 【问题描述】:我想将所有包含“特殊”一词的文件和目录重命名为“常规”。它应该保持区分大小写,这样“特殊”就不会变成“常规”。
如何在 bash 中递归执行此操作?
【问题讨论】:
Recursively rename files using find and sed的可能重复 【参考方案1】:尝试这样做(需要 bash --version
>= 4):
shopt -s globstar
rename -n 's/special/regular/' **
当您的测试正常时移除-n
开关
还有其他同名的工具可能会也可能不会做到这一点,所以要小心。
如果您运行以下命令 (GNU
)
$ file "$(readlink -f "$(type -p rename)")"
你会得到类似
的结果.../rename: Perl script, ASCII text executable
且不包含:
ELF
那么这似乎是正确的工具 =)
如果不是,则将其设为 Debian
和派生类 Ubuntu
的默认值(通常已经如此):
$ sudo update-alternatives --set rename /path/to/rename
(将/path/to/rename
替换为perl's rename
命令的路径。
如果你没有这个命令,搜索你的包管理器安装它或do it manually
最后但同样重要的是,这个工具最初是由 Perl 的父亲 Larry Wall 编写的。
【讨论】:
shopt -s globstar
是干什么用的?
它启用了 bash 功能**
(代表递归)可能已经启用。
我的主目录中有大约 1700 个文件要重命名。这似乎太多了,这实际上是错误消息中的文本,太多的参数。
为了避免错误使用 for i in **;重命名 's/'s/old/new/g'
【参考方案2】:
使用find
的解决方案:
仅重命名文件:
find /your/target/path/ -type f -exec rename 's/special/regular/' '' \;
仅重命名目录:
find /your/target/path/ -type d -execdir rename 's/special/regular/' '' \+
要重命名文件和目录:
find /your/target/path/ -execdir rename 's/special/regular/' '' \+
【讨论】:
@speakr,很好的解决方案,谢谢!您能否提供有关它正在做什么的更多详细信息,尤其是这部分“''\”?快速浏览并没有帮助,所以我认为这些信息对其他人也可能有用。 @DmitryGonchar 看看-exec command ;
中的find manpage。
@ThiloSchulz 可以,但您必须使用find … -execdir … '' +
而不是… '' \;
。添加了说明。
如果文件很多,在find中利用正则表达式,对于上面的最后一个例子你使用:find /your/target/path/ -regex '.*special.*' -execdir rename 's/special/regular/' '' \+
,否则会很慢!
太好了,谢谢。但是,在 OSX 上似乎没有完成 recursively
的工作......【参考方案3】:
如果你不介意安装其他工具,那么你可以使用rnm:
rnm -rs '/special/regular/g' -dp -1 *
它将遍历所有目录/子目录(因为-dp -1
),并将其名称中的 special 替换为 regular。
【讨论】:
这是从 Homebrew 安装的吗? @LokMac :我不认为它在 homebrew 中可用(我只为基于 debian 的操作系统打包二进制文件),如果你有 automake,你可以在任何 Unix 系统中安装它(说明在 @ 987654322@). 很棒的工具!为我工作!【参考方案4】:对于那些只想重命名目录的人,你可以使用这个命令:
find /your/target/path/ -type d -execdir rename 's/special/regular/' '' \;
注释类型现在是d
用于目录,并使用-execdir
。
我还没有弄清楚如何一次性重命名文件和目录。
之前有人评论说,一旦它重命名了根文件夹,它就不能再遍历文件树了。有一个可用的-d
开关可以从下到上进行深度遍历,所以我相信根会最后重命名:
find -d /your/target/path/ -type d -execdir rename 's/special/regular/' '' \;
来自手册页 (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.
【讨论】:
如果有人能澄清在一次通过中对文件和目录执行命令的操作,我将不胜感激,我将使用命令更新此答案。【参考方案5】:@speakr's answer 是我的线索。
如果使用 -execdir 来转换文件和目录,您还需要从所示示例中删除 -type f
。要拼写出来,请使用:
find /your/target/path/ -execdir rename 's/special/regular/' '' \+
此外,如果您想在给定的文件名中用regular
替换所有 出现的special
,而不仅仅是第一次出现,请考虑将g
(全局)标志添加到正则表达式。例如:
find /your/target/path/ -execdir rename 's/special/regular/g' '' \+
会将special-special.jpg
转换为regular-regular.jpg
。如果没有全局标志,您最终会得到regular-special.jpg
。
仅供参考:默认情况下,Mac OSX 上未安装 GNU Rename。如果您使用的是Homebrew package manager,brew install rename
会解决这个问题。
【讨论】:
这个正确的句柄包括文件夹吗?例如/special/regular/regular-specilal.jpeg
【参考方案6】:
这是另一种更便携的方法,并且不依赖于rename
命令(因为它可能需要不同的参数,具体取决于发行版)。
它递归地重命名文件和目录:
find . -depth -name "*special*" | \
while IFS= read -r ent; do mv $ent $ent%special*regular$ent##*special; done
它的作用
使用带有-depth
参数的find 通过执行深度优先遍历来重新排序结果(即,目录中的所有条目都显示在目录本身之前)。
进行模式替换以仅修改路径中最后出现的 regular。
这样首先修改文件,然后修改每个父目录。
示例
给出以下树:
├── aa-special-aa
│ └── bb-special
│ ├── special-cc
│ ├── special-dd
│ └── Special-ee
└── special-00
它以特定顺序生成那些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
获取以下树:
├── aa-regular-aa
│ └── bb-regular
│ ├── regular-cc
│ ├── regular-dd
│ └── Special-ee
└── regular-00
【讨论】:
非常感谢您的解释,完全符合我的需要。【参考方案7】:对于rename
版本rename from util-linux 2.23.2
,以下命令对我有用:
find . -type f -exec rename mariadb mariadb-proxy '' \;
【讨论】:
【参考方案8】:正如 Rui Seixas Monteiro 所提到的,最好将 -iregex 模式选项与 Find 命令一起使用。我发现了以下作品,并在 U007D 提到的正则表达式中包含了全局标志:
文件:
find /path/ -type f -iregex '.*special.*' -execdir rename 's/special/regular/g' '' \+;
目录:
find /path/ -type d -iregex '.*special.*' -execdir rename 's/special/regular/g' '' \+;
文件和目录
find /path/ -iregex '.*special.*' -execdir rename 's/special/regular/g' '' \+;
【讨论】:
以上是关于ubuntu /bash 下递归重命名文件和目录的主要内容,如果未能解决你的问题,请参考以下文章