grep funktioniert nicht mit Dateinamen aus For-Schleife

grep funktioniert nicht mit Dateinamen aus For-Schleife

Ich lerne Bash-Skripting und versuche, die Ergebnisse mit einem verschachtelten Grep in einer For-Schleife zu filtern:

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

und das ist das Skript:

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

Die Idee dahinter ist, dass auf jede Datei, die diesen Inhalt enthält, _AACOperationen angewendet werden. In diesem speziellen Fall drucken Sie einfach auf stdout, um zu bestätigen, dass die Ergebnisse richtig sind.

das Problem ist: nichts kommt über die ifAnweisung hinaus. mir fehlt also ich-weiß-nicht-was. Das Einzige, was funktioniert, ist die printf "input...Zeile.

Was vermisse ich?

Antwort1

Wenn Sie alle Dateien abgleichen möchten, deren Name wie .../something_AACxyz, _AACim letzten Dateinamenteil steht, fügen Sie den _AACTeil einfach direkt zum Glob-Muster/Platzhalter hinzu:

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

Wenn Sie Dateinamen möchten, die _AACin jedem Teil vorkommen können, können Sie (in Bash) Folgendes tun:

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

Hier erhalten Sie auch die Dateien, die zu den Globs passen, aber nicht haben _AAC.


In jedem Fall können Sie unter Bash extglobdas Muster @(...|...)anstelle der Klammererweiterung auch aktivieren und neu schreiben:

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

Die Klammererweiterung erzeugt mehrere unterschiedliche Globs, während @(..)es mit nur ein einzelner Glob ist. (also *.{foo,bar}ist dasselbe wie *.foo *.bar) Mit nullglobset spielen die nicht übereinstimmenden keine Rolle, aber wenn Sie failglobset hätten, würde schon ein einziger nicht übereinstimmender Glob ausreichen, um den gesamten Befehl fehlschlagen zu lassen.

Antwort2

Wo Ihr Skript sagt:

  if grep -qF _AAC $file; then

es heißt: „Wenn der Inhalt der genannten Datei $filedie wörtliche Zeichenfolge enthält _AAC, dann ...“ führe den Inhalt des thenBlocks aus.

Wenn Sie stattdessen in der Zeichenfolge suchen möchten, _AACdie sich aus der Erweiterung der Variablen ergibt $file(also prüfen möchten, ob _AAC im Dateinamen selbst vorkommt), bashmüssen Sie in Folgendes schreiben:

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

Oder, wie @roaima anmerkt, die gesuchte Zeichenfolge kann in die Platzhalterdateispezifikation aufgenommen werden.

verwandte Informationen