![将一组文件中的所有冒号替换为破折号?](https://linux22.com/image/117017/%E5%B0%86%E4%B8%80%E7%BB%84%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E5%86%92%E5%8F%B7%E6%9B%BF%E6%8D%A2%E4%B8%BA%E7%A0%B4%E6%8A%98%E5%8F%B7%EF%BC%9F.png)
我尝试使用以下命令将某些子文件夹中的文件名中的所有冒号替换为破折号:
find . -type f -name "*:*" -exec rename -n 's/:/-/g' {} +
但是我收到一条错误消息
rename: not enough arguments
通过谷歌搜索,这似乎是因为我的重命名版本与上述命令所需的版本不同。那么我如何才能将此命令“转换”为适用于我的重命名版本的命令呢?
我的重命名版本是“rename from util-linux 2.28.2”
答案1
rename
是的, Linux 系统上的命令有两个主要的不相关且完全不兼容的变体。
一个perl
(几十年前作为示例脚本开始,并伴随发行了perl
很长一段时间,现在您会发现它是一个或多个带有一些扩展的独立包)。这个被称为rename
或有时prename
在系统中rename
是其他东西。
这就是命令行所期望的。
rename
而且 . 的实用性非常有限util-linux
。有时在是 的rename.ul
系统上会调用该。rename
perl
rename
使用该字符串,您只能将一个字符串替换为另一个字符串。您可以这样做-execdir rename : - {} +
,但这只会替换一个冒号(12:30:00.log
-> 12-30:00.log
)。
在这里,您可以rename
手动实现:
find . -name '*:*' -type f -print0 | perl -0ne '
rename $_, s{[^/]+$}{$& =~ y/:/-/r}res or warn "rename $_: $!"'
(这里确保仅在文件的基本名称中将:
s 替换为,就好像目录包含 一样,这会失败)。-
:
或者使用 shell 而不是perl
进行替换并调用mv
重命名(这里使用bash
和ksh 参数扩展运算符,如果没有,${var//pattern/replacement}
可以bash
用ksh
或替换):zsh
bash
find . -name '*:*' -type f -exec bash -c '
for file do
base=${file##*/}
mv "$file" "${file%/*}/${base//:/-}"
done' bash {} +
或者使用zsh
及其zmv
功能:
autoload zmv
zmv '(**/)(*:*)(#qD.)' '$1${2//:/-}'
答案2
没有rename
:
find . -type f -name '*:*' -execdir bash -c 'echo mv "$1" "${1//:/-}"' bash {} \;
如图所示尝试一下,echo
如果您认为效果正确,则将其删除。
这用于以每个找到的文件名作为参数-execdir
来执行。bash -c 'mv "$1" "${1//:/-}"'
由 创建的内壳bash -c
将接收一个名称 in$1
并将${1//:/-}
扩展为该名称,并全部:
替换为-
。
(命令末尾的尾部是在子 shell中bash
给出的内容。)$0
bash -c