Рекурсивная замена строки в файлах

Рекурсивная замена строки в файлах

Я хочу заменить обратную косую черту в строке page_path\example_filename.txtна прямую косую черту. Я также хочу иметь возможность запустить это в большой файловой системе и рекурсивно искать во всех каталогах.

Я нашел кого-то в сети, кто сказал использовать grep, xargs, и sed, но я не смог заставить это работать. Я пробовал разные варианты разделителей и экранирующих символов, но не получил этого.

Вот команда, которую я пытался выполнить:
grep -lr -e 'page_path\\' * | xargs sed -i 's/page_path\/page_path//g'

Заранее спасибо.

решение1

При использовании grep | xargs, у вас возникнут проблемы с пробелами, кавычками, обратными косыми чертами (и, возможно, другими элементами в зависимости от xargsреализации) в именах файлов.

С помощью реализаций GNU grepи xargsвы можете избежать этих проблем, используя: , grep -lZr ... | xargs -r0 sed ...который использует нулевые байты в качестве разделителя.

А теперь о команде sed: Хитрость в том, что вы можете использовать вместо нее s/a/b/любой другой символ в качестве разделителя, например s#a#b#:

sed -i 's#page_path\\#page_path/#g'

решение2

Также для этого можно использовать find:

find /your/path -type f -exec grep -l 'page_path\\' {} \; -exec sed -i 's#page_path\\#page_path/#g' {} \;

Второе выполнение будет выполнено только в том случае, если первое было выполнено успешно, и у вас не возникнет проблем с непечатаемыми или экранированными символами в именах файлов.

решение3

Зачем тратить циклы ЦП на вызов всех этих команд, когдаБашимеет встроенную функциональность, позволяющую сделать это с НАМНОГО меньшим количеством набора текста?

Пример

str='page_path\example_filename.txt'
echo "${str//\\/\/}"

Выход

page_path/example_filename.txt

решение4

ripgrepЗдесь также может помочь: замените foo на то, что вам нужно, а затем измените и в rgвызове, и в sedвыражении.

rg foo --files-with-matches | xargs sed -i 's/foo/bar/g'

Если в именах ваших файлов есть пробелы, укажите ripgrep, чтобы он разделял их нулевым байтом.

rg foo --files-with-matches -0 | xargs -0 sed -i 's/foo/bar/g'

источник:https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#поиск-и-замена

Связанный контент