Bash 重命名通配符的命令行

Bash command-line to rename wildcard

在我的 /opt/myapp 目录中,我有一个远程自动化进程,它将删除 <anything>-<version>.zip 形式的文件,其中 <anything> 可以字面意思是 any 字母数字文件名,其中 <version> 将是版本号。因此,此自动化流程将交付的示例如下:

等通过此问题范围之外的控制,我 保证 在任何给定时间 /opt/myapp 下只会存在这些 ZIP 文件中的一个。我需要编写 Bash shell 命令 来重命名这些文件并将它们移动到 /opt/staging。对于重命名,ZIP 文件需要删除其版本。因此 /opt/myapp/<anything>-<version>.zip 被重命名并移动到 /opt/staging/<anything>.zip。使用上面的例子:

目录移动很明显也很容易,但是重命名让我抓狂。我需要以某种方式保存 <anything>,然后稍后在命令中重新访问它。 命令必须是通用的并且不能带参数。

到目前为止,我最好的尝试(甚至没有接近成功)是:

file=*.zip; file=?; mv file /opt/staging

关于如何做到这一点有什么想法吗?

for file in *.zip; do
  [[ -e $file ]] || continue # handle zero-match case without nullglob
  mv -- "$file" /opt/staging/"${file%-*}.zip"
done

${file%-*} 删除文件名中最后一个 - 之后的所有内容。因此,我们将 fizz-0.1.0.zip 更改为 fizz,然后添加前导 /opt/staging/ 和尾随 .zip.


为了使其更通用(使用多个扩展),请参阅以下函数(可作为命令调用;函数体也可以用 #!/bin/bash shebang 放入脚本中,如果删除了 local 声明):

stage() {
  local file ext
  for file; do
    [[ -e $file ]] || continue
    [[ $file = *-*.* ]] || {
      printf 'ERROR: Filename %q does not contain a dash and a dot\n' "$file" >&2
      continue
    }
    ext=${file##*.}
    mv -- "$file" /opt/staging/"${file%-*}.$ext"
  done
}

...定义该函数后,您可以 运行:

stage *.zip *.txt

...或您选择的任何其他模式。

f=foo-1.3.4.txt
echo ${f%%-*}.${f##*.}