当我更改任何配置时,我会制作带有后缀 .original 的原始文件的副本。现在我正在编写一个简单的脚本,它将查找所有 *.original 文件并使用两个版本,即带或不带 .original 后缀。
我确实使用带有正则表达式的命令locate
来避免文件与original
路径中间的字符串不匹配。
我的命令是locate --regex ^.*\\.original$
完美运行in terminal
。它查找所有以 .original 后缀结尾的文件,例如file.original
然而in bash script
当我在中使用相同的命令时,for loop
它会返回诸如file.original
file-original
file_original
等的变体。
我应该如何修改正则表达式或 for 循环以仅获取 .original 文件?
我的外壳是:
$ echo $BASH
/usr/bin/bash
我的 bash 脚本是:
#!/usr/bin/bash
echo "Plain locate command:"
locate --regex ^.*\\.original$ | grep test
echo "For loop:"
for file in `locate --regex ^.*\\.original$ | grep test`; do
echo $file
done
您可以使用它进行测试:
mkdir /tmp/test
touch /tmp/test/file.original
touch /tmp/test/file-original
touch /tmp/test/file_original
updatedb
locate --regex ^.*\\.original$
在我的终端中它会发现:
/tmp/test/file.original
但我的脚本会发现:
Plain locate command:
/tmp/test/file.original
For loop:
/tmp/test/file-original
/tmp/test/file.original
/tmp/test/file_original
答案1
反引号需要更多转义。这是您应该更喜欢的原因之一$()
(请参阅此答案中的“反斜杠乐趣”:$(stuff)
和 和有什么区别`stuff`
?)。
由于反引号内没有足够的转义,当字符串最终被解释为正则表达式时,您想要转义的点不会被转义。
将相关行更改为:
for file in $(locate --regex '^.*\.original$' | grep test); do
笔记:
我使用单引号来方便地处理反斜杠和星号。在您的原始代码中,未加引号和未转义的星号可以触发文件名扩展。
^.*
正则表达式中没有任何改变。单引号\.original$
就足够了。我决定保留^.*
只是为了指出文件名扩展的可能性。习惯于引用变量(例如
echo "$file"
)。链接的答案$()
也建议引用,但在我们的for
循环中引用将是错误的。不引用$()
也是错误的。两者都是错误的,因为……一般来说
for
像这样构建循环通常是错误的。这是Bash 的第一大陷阱。要对locate
better 的输出执行某些操作xargs
,最好将其作为以 null 结尾的字符串:locate -0 … | grep -z … | xargs -r0 …
这些选项不可移植。