学习 bash 脚本,我正在尝试使用 for 循环中的嵌套 grep 来过滤结果:
sample filenames:
this-file_AAC.txt
this-other_file_AAAC.txt
yep-a-file_AAC.nfo
oops_another_one.reamde
这是脚本:
shopt -s globstar nullglob dotglob
for file in ./**/*.{txt,reamde,nfo}; do
printf "input: ${file}\n"
if grep -qF _AAC $file; then
printf "output: ${file}\n"
# do stuff with $file
fi
done
这个想法是任何包含的文件_AAC
都将对其应用操作;在这种特定情况下,只需打印到标准输出即可确认结果是否正确。
问题是:没有什么可以超越if
陈述。所以我错过了我不知道什么。唯一有效的就是这printf "input...
条线。
我缺少什么?
答案1
如果要匹配最后一个文件名部分中名为.../something_AACxyz
,的所有文件,只需将该部分直接添加到 glob 模式/通配符中:_AAC
_AAC
for file in ./**/*_AAC*.{txt,reamde,nfo}; do
如果你希望文件名_AAC
可以出现在任何部分,你可以这样做(在 Bash 中):
for file in ./**/*.{txt,reamde,nfo}; do
if [[ $file == *_AAC* ]]; then
echo "'$file' contains _AAC"
else
echo "'$file' has NO _AAC"
fi
done
在这里,您还可以获得与 glob 匹配的文件,但没有_AAC
.
无论如何,在 Bash 上,您还可以启用extglob
并重写模式,@(...|...)
而不是使用大括号扩展:
for file in ./**/*_AAC*.@(txt|reamde|nfo); do
大括号扩展产生多个不同的 glob,而@(..)
它只是一个单一的 glob。 (即*.{foo,bar}
与 相同*.foo *.bar
)nullglob
使用 set 时,不匹配的项并不重要,但如果您设置了failglob
,则仅一个不匹配的项就足以使整个命令失败。
答案2
你的脚本说:
if grep -qF _AAC $file; then
它的意思是,“如果指定文件的内容$file
包含文字字符串,_AAC
那么......”执行块的内容then
。
如果您的意思是_AAC
在变量扩展产生的字符串中进行搜索$file
(即检查 _AAC 是否出现在文件名本身中),那么在 中bash
,您需要编写:
if grep -qF _AAC <<< "$file"; then
或者,正如 @roaima 指出的那样,您正在搜索的文字字符串可以包含在通配符文件规范中。