grep não funciona com o nome do arquivo do loop for

grep não funciona com o nome do arquivo do loop for

aprendendo scripts bash e estou tentando filtrar resultados com um grep aninhado em um loop for:

sample filenames:
  this-file_AAC.txt
  this-other_file_AAAC.txt
  yep-a-file_AAC.nfo
  oops_another_one.reamde

e este é o roteiro:

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

a ideia é que qualquer arquivo que contenha _AACterá operações aplicadas a ele; neste caso específico, basta imprimir em stdout para confirmar que os resultados estão corretos.

O problema é: nada passa da ifafirmação. então estou sentindo falta de não sei o quê. tudo o que funciona é a printf "input...linha.

o que estou perdendo?

Responder1

Se você quiser corresponder todos os arquivos nomeados como .../something_AACxyz, _AACna última parte do nome do arquivo, basta adicionar a _AACparte diretamente ao padrão glob/curinga:

for file in ./**/*_AAC*.{txt,reamde,nfo}; do

Se você quiser nomes de arquivos que _AACpossam aparecer em qualquer parte, você pode fazer (no Bash):

for file in ./**/*.{txt,reamde,nfo}; do
    if [[ $file == *_AAC* ]]; then
         echo "'$file' contains _AAC"
    else
         echo "'$file' has NO _AAC"
    fi
done

Aqui, você também obtém os arquivos que correspondem aos globs, mas não possuem a extensão _AAC.


De qualquer forma, no Bash, você também pode ativar extglobe reescrever o padrão em @(...|...)vez da expansão de chaves:

for file in ./**/*_AAC*.@(txt|reamde|nfo); do

A expansão da chave produz vários globos distintos, enquanto @(..)é apenas um único globo. (ou seja, *.{foo,bar}é o mesmo que *.foo *.bar) Com nullglobset os não correspondentes não importam, mas se você tivesse failglobdefinido, apenas um não correspondente seria suficiente para falhar em todo o comando.

Responder2

Onde seu script diz:

  if grep -qF _AAC $file; then

está dizendo, "se o conteúdo do arquivo nomeado $filecontiver a string literal, _AACentão ...." execute o conteúdo do thenbloco.

Se o que você quer dizer é procurar _AACna string resultante da expansão da variável $file(ou seja, para verificar se _AAC aparece no próprio nome do arquivo), então em bash, você precisa escrever:

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

Ou, como aponta @roaima, a string literal que você está procurando pode ser incluída na especificação do arquivo curinga.

informação relacionada