获取具有特定字符数的所有文件名

Höl*_*lin 3 regular-expression for mv

我想更改所有文件名,它们的长度精确为 16 个字符(数字和小写字母)。我尝试[0-9a-z]{16}了以下代码片段中的[0-9a-z]\{16\}占位符regX,但它不起作用。

for file in <regX>
do
  mv "$file" "${file}.txt"
done
Run Code Online (Sandbox Code Playgroud)

Kus*_*nda 5

shell 通配模式不是正则表达式。它们可能看起来很相似,但在某些方面的工作方式却截然不同。

正则表达式[0-9a-z]{16}匹配包含上述字符范围的 16 个字符的字符串(包含匹配的字符串可能更长)。

等效的 shell 通配模式类似于

*[0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z]*
Run Code Online (Sandbox Code Playgroud)

这是因为

  1. 通配模式不支持“重复前 N 次”的修饰符。
  2. 默认情况下,通配符模式固定在开头和结尾。这就是我*在模式的开头和结尾插入的原因。A*匹配任意数量的任意字符。如果您想精确匹配16 个字符,请将其删除。

您可以使用 Perl 创建一个 16 的字符串[0-9a-z]

$ pattern="$( perl -e 'print "[0-9a-z]" x 16' )"
Run Code Online (Sandbox Code Playgroud)

使用bash,您可以选择迭代当前目录中的所有名称,然后测试名称是否与您的正则表达式匹配:

for name in *; do
    if [[ -f "$name" ]] && [[ "$name" =~ ^[0-9a-z]{16}$ ]]; then
        echo mv "$name" "$name.txt"
    fi
done
Run Code Online (Sandbox Code Playgroud)

echo一旦您知道它正在做正确的事情,请将其删除。

请注意,我已经锚定了该模式,以便较长的名称不会匹配。我还通过测试确保-f我们获得的名称实际上只是常规文件的名称。