将一组文件中的所有冒号替换为破折号?

将一组文件中的所有冒号替换为破折号?

我尝试使用以下命令将某些子文件夹中的文件名中的所有冒号替换为破折号:

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系统上会调用该。renameperlrename

使用该字符串,您只能将一个字符串替换为另一个字符串。您可以这样做-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}可以bashksh或替换):zshbash

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给出的内容。)$0bash -c

相关内容