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, _AAC
Operationen 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 if
Anweisung 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
, _AAC
im letzten Dateinamenteil steht, fügen Sie den _AAC
Teil einfach direkt zum Glob-Muster/Platzhalter hinzu:
for file in ./**/*_AAC*.{txt,reamde,nfo}; do
Wenn Sie Dateinamen möchten, die _AAC
in 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 extglob
das 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 nullglob
set spielen die nicht übereinstimmenden keine Rolle, aber wenn Sie failglob
set 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 $file
die wörtliche Zeichenfolge enthält _AAC
, dann ...“ führe den Inhalt des then
Blocks aus.
Wenn Sie stattdessen in der Zeichenfolge suchen möchten, _AAC
die sich aus der Erweiterung der Variablen ergibt $file
(also prüfen möchten, ob _AAC im Dateinamen selbst vorkommt), bash
müssen Sie in Folgendes schreiben:
if grep -qF _AAC <<< "$file"; then
Oder, wie @roaima anmerkt, die gesuchte Zeichenfolge kann in die Platzhalterdateispezifikation aufgenommen werden.