Bash 重命名通配符的命令行
Bash command-line to rename wildcard
在我的 /opt/myapp
目录中,我有一个远程自动化进程,它将删除 <anything>-<version>.zip
形式的文件,其中 <anything>
可以字面意思是 any 字母数字文件名,其中 <version>
将是版本号。因此,此自动化流程将交付的示例如下:
fizz-0.1.0.zip
buzz-1.12.35.zip
foo-1.0.0.zip
bar-3.0.9.RC.zip
等通过此问题范围之外的控制,我 保证 在任何给定时间 /opt/myapp
下只会存在这些 ZIP 文件中的一个。我需要编写 Bash shell 命令 来重命名这些文件并将它们移动到 /opt/staging
。对于重命名,ZIP 文件需要删除其版本。因此 /opt/myapp/<anything>-<version>.zip
被重命名并移动到 /opt/staging/<anything>.zip
。使用上面的例子:
/opt/myapp/fizz-0.1.0.zip
=> /opt/staging/fizz.zip
/opt/myapp/buzz-1.12.35.zip
=> /opt/staging/buzz.zip
/opt/myapp/foo-1.0.0.zip
=> /opt/staging/foo.zip
/opt/myapp/bar-3.0.9.RC.zip
=> /opt/staging/bar.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##*.}
在我的 /opt/myapp
目录中,我有一个远程自动化进程,它将删除 <anything>-<version>.zip
形式的文件,其中 <anything>
可以字面意思是 any 字母数字文件名,其中 <version>
将是版本号。因此,此自动化流程将交付的示例如下:
fizz-0.1.0.zip
buzz-1.12.35.zip
foo-1.0.0.zip
bar-3.0.9.RC.zip
等通过此问题范围之外的控制,我 保证 在任何给定时间 /opt/myapp
下只会存在这些 ZIP 文件中的一个。我需要编写 Bash shell 命令 来重命名这些文件并将它们移动到 /opt/staging
。对于重命名,ZIP 文件需要删除其版本。因此 /opt/myapp/<anything>-<version>.zip
被重命名并移动到 /opt/staging/<anything>.zip
。使用上面的例子:
/opt/myapp/fizz-0.1.0.zip
=>/opt/staging/fizz.zip
/opt/myapp/buzz-1.12.35.zip
=>/opt/staging/buzz.zip
/opt/myapp/foo-1.0.0.zip
=>/opt/staging/foo.zip
/opt/myapp/bar-3.0.9.RC.zip
=>/opt/staging/bar.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##*.}