2

我在这样的目录中有文件:

asdfs54345gsdf.pdf
gsdf6456wer.pdf
oirt4534724wefd.pdf

我想将所有文件重命名为数字+ .pdf,以便将上述文件重命名为:

54345.pdf
6456.pdf
4534724.pdf

最好的是原生 Bash 命令或脚本(OSX 10.6.8)

我收集到的一些线索包括

sed 's/[^0-9]*//g' input.txt 
sed 's/[^0-9]*//g' input.txt > output.txt 
sed -i 's/[^0-9]*//g' input.txt 
echo ${A//[0-9]/} rename 's/[0-9] //' *.pdf 
4

1 回答 1

6

这可以做到:

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。对于这个小组,我手头没有进一步阅读的来源。

于 2012-04-27T23:53:26.957 回答