在 ubuntu /bash 下递归重命名文件和目录
- 2024-10-29 08:35:00
- admin 原创
- 54
问题描述:
我想将所有包含单词“special”的文件和目录重命名为“regular”。它应该保持区分大小写,这样“Special”就不会变成“regular”。
我怎样才能在 Bash 中递归地执行此操作?
解决方案 1:
使用以下解决方案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/' '{}' +
解决方案 2:
尝试这样做(需要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
。
如果你没有此命令,请搜索你的包管理器来安装它或手动执行
最后但同样重要的一点是,这个工具最初是由 Perl 之父 Larry Wall 编写的。
解决方案 3:
这是另一种更便携且不依赖于rename
命令的方法(因为它可能需要根据发行版的不同而不同的参数)。
它以递归方式重命名文件和目录:
find . -depth -name "*special*" | \nwhile IFS= read -r ent; do mv $ent ${ent%special*}regular${ent##*special}; done
它的作用
使用带参数的 find通过执行深度优先遍历
-depth
对结果进行重新排序(即,目录中的所有条目都显示在目录本身之前)。进行模式替换以仅修改路径中最后一次出现的常规内容。
这样,文件首先被修改,然后每个父目录被修改。
例子
给出以下树:
├── 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
解决方案 4:
如果您不介意安装其他工具,那么您可以使用rnm:
rnm -rs '/special/regular/g' -dp -1 *
它将遍历所有目录/子目录(因为)并用常规-dp -1
替换其名称中的特殊内容。
解决方案 5:
@speakr 的回答对我来说是线索。
如果使用 -execdir 来转换文件和目录,您还需要-type f
从显示的示例中删除。要说明这一点,请使用:
find /your/target/path/ -execdir rename 's/special/regular/' '{}' +
此外,g
如果您想替换给定文件名中所有出现的而不是只替换第一次出现的 ,请考虑向正则表达式添加 (全局) 标志。例如:special
`regular`
find /your/target/path/ -execdir rename 's/special/regular/g' '{}' +
将转换special-special.jpg
为regular-regular.jpg
。如果没有全局标志,您最终将得到regular-special.jpg
。
仅供参考:GNU Rename 未默认安装在 Mac OSX 上。如果您使用Homebrew 包管理器,brew install rename
将会解决这个问题。
解决方案 6:
正如 Rui Seixas Monteiro 所提到的,最好将 -iregex 模式选项与 Find 命令一起使用。我发现以下方法有效,并在正则表达式中包含 U007D 提到的全局标志:
文件:
查找 /path/-type f-iregex'.*special.*'-execdir 重命名's/special/regular/g''{}'+;
目录:
查找 /path/-type d -iregex'.*special.*'-execdir 重命名's/special/regular/g''{}'+;
文件和目录
查找 /path/-iregex'.*special.*'-execdir 重命名's/special/regular/g''{}'+;
解决方案 7:
对于那些只想重命名目录的人来说,你可以使用这个命令:
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.
解决方案 8:
对于rename
版本,rename from util-linux 2.23.2
以下命令对我有用:
find . -type f -exec rename mariadb mariadb-proxy '{}' ;
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件