Reemplazar recursivamente cadenas en archivos

Reemplazar recursivamente cadenas en archivos

Quiero reemplazar la barra invertida en la cadena page_path\example_filename.txtcon una barra diagonal. También quiero poder ejecutar esto en un sistema de archivos grande y hacer que busque recursivamente en todos los directorios.

Encontré a alguien en la web que me dijo que usara grep, xargsy sedpero no pude hacerlo funcionar. He estado probando diferentes variaciones de delimitadores y caracteres de escape, pero no lo conseguí.

Aquí está el comando que estaba intentando ejecutar:
grep -lr -e 'page_path\\' * | xargs sed -i 's/page_path\/page_path//g'

Gracias de antemano.

Respuesta1

Con grep | xargs, obtienes problemas con espacios en blanco, comillas, barras invertidas (y posiblemente más dependiendo de la xargsimplementación) en los nombres de archivos.

Con las implementaciones GNU de grepy xargs, puedes evitar esos problemas usando: grep -lZr ... | xargs -r0 sed ...que usa cero bytes como delimitador.

Y ahora con respecto al comando sed: el truco es que puedes usarlo en lugar de s/a/b/cualquier otro carácter como separador, por ejemplo s#a#b#:

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

Respuesta2

También puedes usar buscar para eso:

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

El segundo ejecutable se ejecutará solo si el primero tuvo éxito y no tendrá problemas con caracteres no imprimibles o que no necesiten caracteres en los nombres de los archivos.

Respuesta3

¿Por qué desperdiciar ciclos de CPU llamando a todos esos comandos cuandointento¿Ha creado una funcionalidad para hacerlo con MUCHO menos tipeo?

Ejemplo

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

Producción

page_path/example_filename.txt

Respuesta4

ripgrepTambién puede ayudar aquí, reemplazar foo con lo que coincide y luego cambiar tanto en rgla invocación como en sedla expresión.

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

Si sus archivos pueden tener espacios en blanco en sus nombres, dígale a ripgrep que los separe por byte NULL

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

fuente:https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#search-and-replace

información relacionada