如何通过正则表达式重命名批量文件?

How to rename bulk files by regex?

我有一堆文件从 wget 操作中吐出。很多都有这样的文件名:

bootstrap.min.css?v=30cad4497c.css
font-awesome.min.css?v=30cad4497c.css
screen.css?v=30cad4497c.css

是的,这些是文件名、问号和等号等等。

?v=30cad4497.css 东西出现的原因我知道。如何重命名所有文件以删除“?”之后的所有内容角色?

我很乐意为此编写几行 shell 脚本,但我不想不得不搞砸 python/node/ruby/whatever。

在bash中:

for file in *[?]* ; do mv $file ${file%%[?]*} ; done

*[?]* 表示匹配文件名中包含问号的文件。 ${file%%glob} 表示在字符串的末尾 剥离所有匹配glob 的文本。 ${file##glob} 表示去掉字符串开头所有与 glob 匹配的文本。请注意,这些是 文件 glob,而不是正则表达式。文件 glob 是我们经常用来匹配 bash.

中的文件

works well with the specific filenames at hand, but, for general robustness, the variable references should be double-quoted to ensure that they're used as-is (to protect their values from shell expansions):

for file in *\?* ; do mv "$file" "${file%%\?*}"; done

还要注意我是如何使用 \? 来匹配 literal ? 的,因为它是意图的更直接表达 - 尽管使用字符 set 仅包含一个元素 ([?]) 也可以。

关于 Pattern Matching Notation 使用的注释:

  • 正如 Danny 指出的那样,模式虽然关系很远,但 不是 正则表达式(正则表达式),上面的 link 到 POSIX规范描述了它们的具体语法。

  • 模式不只有pathname expansion (globbing), but also in parameter expansion中使用,其中${file%%\?*}是一个例子:

    • %% - 与 % 相反 - 从 $file 的值中去除 最长的 后缀,匹配 后面的模式
    • 至少对于仅包含单个 ? 的示例输入,通过 % 剥离 最短 后缀也可以(${file%\?*}).

请注意,在参数扩展中使用模式,例如 %% 独立于 路径名扩展(通配) ,如以下示例所示:

$ foo='bar'; echo "${foo%a*}"
b  # suffix 'a' followed by any chars. stripped

此外,在Bash(以及Ksh和Zsh)中,您还可以在==运算符的RHS上使用模式(注意这是不是 POSIX 标准的一部分):

$ [[ foo == 'f'* ]] && echo YES
YES

请注意 * 等模式元字符必须 不加引号 才能被识别(regex-matching operator, =~ 也是如此)。