Grep несколько файлов, имена которых хранятся в переменной - PullRequest
0 голосов
/ 12 июля 2020

Рассмотрим переменную files:

$ echo $files
1.txt 2.txt 3.txt

Есть ли способ сообщить grep, что он должен использовать grep для каждого файла, появляющегося в переменной, для одной строки? Я пробовал:

$ grep "string" "$files"

, но получаю ошибку 1.txt 2.txt 3.txt No such file of directory. Прошло много времени с тех пор, как я использовал оболочку для работы, поэтому я не помню, как это сделать.

1 Ответ

9 голосов
/ 12 июля 2020

Со списком имен файлов, хранящихся в files, например,

files="1.txt 2.txt 3.txt"

Когда вы цитируете "$files" (хорошее цитирование вашей переменной) и пытаетесь использовать "$files" с помощью команды grep разбиение на содержимое $files не происходит? Зачем? Цитирование предотвращает разделение слов , поэтому grep пытается найти файл с именем "1.txt 2.txt 3.txt", который, конечно, не завершается и генерирует вашу ошибку.

Вы можете использовать grep с $files, просто используя $files без кавычек - но это не путь к go. Зачем? При сохранении имен файлов для использования с командой вы должны убедиться, что набор сохраненных файлов может обрабатывать все допустимые имена файлов. Сюда входят имена файлов с пробелами. Если вы попытаетесь использовать метод без кавычек с:

files="file 1.txt file 2.txt file 3.txt"

Использование grep (или любой команды) с $files без кавычек не удастся найти 6 файлов, file, 1.txt, file, 2.txt, file, 3.txt.

Эта проблема подробно описана и обсуждается в BashFAQ # 50 , а конкретно 5. Я создаю команду на основе информации, которая известна только во время выполнения . Решение состоит в том, чтобы хранить ваши имена файлов в массиве (если вам вообще нужно их хранить). Как указывает @Jetchisel, это можно сделать, просто создав files как массив с:

files=(*.txt)

(или files=([1-3].txt), чтобы ограничить выбор 1.txt, 2.txt, 3.txt)

Используя массив, вы можете затем использовать форму в кавычках "${files[@]}", которая предоставит каждое из имен файлов для команды, отдельно цитируемой, например,

grep "string" "${files[@]}"

будет расширяться до:

grep "string" "1.txt" "2.txt" "3.txt"

Таким образом, независимо от имени файла и независимо от того, содержит ли он пробелы, grep увидит правильное имя файла. Например, с:

files=("file 1.txt" "file 2.txt" "file 3.txt")

Использование цитируемой формы массива с grep приведет к:

grep "strings" "file 1.txt" "file 2.txt" "file 3.txt"

Итак, ваша исходная проблема была вызвана подавлением word- разделение , но ваша попытка использовать список имен файлов сама по себе была довольно проблематичной c. Если вам нужно сохранить список имен файлов в переменной, используйте массив по причинам, указанным выше. Если вы можете вообще не хранить их и просто использовать команду grep с глобусом, например *.txt, то вы можете избежать обеих проблем с самого начала.

Дайте мне знать, если у вас возникнут дополнительные вопросы.

...