这可以做到:
for f in *.pdf
do
mv "$f" "${f//[^0-9]/}.pdf"
done
但你最好先尝试:
for f in *.pdf
do
echo mv "$f" "${f//[^0-9]/}.pdf"
done
请注意,abc4.pdf 和 zzz4.pdf 都将重命名为 4.pdf。所以也许你使用mv -i
而不只是 mv。
更新:解释:
我想第一部分很清楚;*.pdf
称为 globbing,匹配所有以 .pdf 结尾的文件。for f in ...
只是迭代它们,每次将 f 设置为其中之一。
for f in *.pdf
do
mv "$f" "${f//[^0-9]/}.pdf"
done
我猜
mv source target
也很清楚。如果文件名为“Unnamed File1”,则需要用引号将其屏蔽,否则 mv 将读取
mv Unnamed File1 1.pdf
这意味着,它有多个文件要移动,Unnamed 和 File1,并将 1.pdf 解释为将两个文件移动到的目录。
好吧,我想真正的问题在这里:
"${f//[^0-9]/}.pdf"
有字符的外部粘合。让
foo=bar
一些变量赋值然后
$foo
${foo}
"$foo"
"${foo}"
是引用它们的四种合法方式。最后两个用于屏蔽空白等,因此在某些情况下没有区别,在某些情况下确实如此。
如果我们把东西粘在一起
$foo4
${foo}4
"$foo"4
"${foo}"4
第一种形式不起作用 - shell 将查找变量 foo4。所有其他 3 个表达式都引用 bar4 - 首先 $foo 被解释为 bar,然后附加 4。对于某些字符,不需要掩码:
$foo/fool
${foo}/fool
"$foo"/fool
"${foo}"/fool
都将以相同的方式解释。所以无论 "${f//[^0-9]/}" 是什么,"${f//[^0-9]/}.pdf" 都是附加到它的 ".pdf"。
我们接近所有奥秘的核心:
${f//[^0-9]/}
这是形式的替换表达式
${variable//pattern/replacement}
- 变量是 $f(我们可以在这里省略大括号内的 $)从上面说是 $f。那很简单!
- 替换是空的——这更容易。
- 但是 [^0-9] 确实很复杂,不是吗?
-
[0-9]
只是从 0 到 9 的所有数字的组,其他组可能是:
[0-4] digits below 5
[02468] even digits
[a-z] lower case letters
[a-zA-Z] all (common latin) characters
[;:,/] semicolon, colon, comma, slash
前面的插入符号 ^ 作为第一个字符是该组的否定:
[^0-9]
表示除 0 到 9(包括点、逗号、冒号、...)之外的所有内容都在组中。一起:
${f//[^0-9]/}
从 $f 中删除所有非数字,并且
"${f//[^0-9]/}.pdf"
附加 .pdf - 整个事情都被掩盖了。
${v//p/r}
和它的朋友(有很多有用的)man bash
在本章中进行了解释Parameter Expansion
。对于这个小组,我手头没有进一步阅读的来源。