У меня есть список файлов, в которых я хочу проверить определенную строку. Если строка существует в файле, я хочу заменить ее новой версией, которая у меня есть. Как проще всего это сделать?
for file in "`grep -l "foo" bar gazi`"; do cp -p --backup=numbered replace "$file"; done
где заменить путь к файлу замены, бар и гази представляют собой список файлов для проверки, и фу интересующая строка поиска.
Если вам требуется дополнительная помощь в формулировании подходящего регулярного выражения для grep (см. Выше), не стесняйтесь спрашивать.
grep может искать в файле строку и вернет 0, если найдет его, вы можете использовать это как часть условного выражения для замены файла, например:
#!/bin/bash
if [ !`/bin/grep -q teststring /path/to/file` ]; then
cp newfile oldfile
fi
Предположительно у вас есть файл со списком файлов в нем? Я не знаю, есть ли у вас статический файл, которым вы заменяете совпадающие файлы, или потенциальную замену для каждого файла. Это обрабатывает второй случай, поскольку в первом просто заменяет $ i.new статическим именем файла.
for i in `cat /var/tmp/listoffiles` ; do
if grep string $i > /dev/null 2>&1 ; then
cp $i $i.old
cp $i.new $i
fi
done
Хотя я согласен со всеми тестами grep, sed действительно может сделать это без теста.
sed -i.BACKUP 's / STRING, ВЫ ХОТИТЕ ЗАМЕНИТЬ / NEW STRING /' файл
Если строки нет, она ничего не сделает. Стоит упомянуть. Из вашего вопроса я не был уверен, пытались ли вы заменить весь файл или только строку в нем.
Правильный способ обработки файлов в цикле в сценарии оболочки - передать команду по конвейеру while
или перенаправить файл в done
заявление while
петля. Это обработает любое имя, кроме тех, которые содержат символы новой строки. Вы не должны использовать форму for f in $(cmd)
.
В этом примере find
это команда, которая создает список файлов:
find . -type f -name "*.txt" | while read -r filename
do
if grep -qs "$string" "$filename" # or use >/dev/null 2>&1 instead of -qs
then
cp "$replacement" "$filename"
fi
done
или, здесь список содержится в файле:
while read -r filename
...
done < "$file_with_list"
Другой метод - использовать xargs
.
Для команды, которая создает список файлов (например, find
):
find . -type f -name "*.txt" -print0 | xargs -0 -I % env string=$string sh 'grep -qs "$string" "%" && cp replacement_file "%"'
Предыдущий метод будет работать в тех случаях, когда имена файлов могут включать символы новой строки.
Если список находится в файле:
xargs -a "$file_with_list" -I % env string=$string sh 'grep -qs "$string" "%" && cp replacement "%"'
Все эти примеры будут работать в тех случаях, когда имена файлов могут включать пробелы.