grep 无法处理 for 循环中的文件名

grep 无法处理 for 循环中的文件名

学习 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 *.barnullglob使用 set 时,不匹配的项并不重要,但如果您设置了failglob,则仅一个不匹配的项就足以使整个命令失败。

答案2

你的脚本说:

  if grep -qF _AAC $file; then

它的意思是,“如果指定文件的内容$file包含文字字符串,_AAC那么......”执行块的内容then

如果您的意思是_AAC在变量扩展产生的字符串中进行搜索$file(即检查 _AAC 是否出现在文件名本身中),那么在 中bash,您需要编写:

  if grep -qF _AAC <<< "$file"; then

或者,正如 @roaima 指出的那样,您正在搜索的文字字符串可以包含在通配符文件规范中。

相关内容