matriculas - sed manual
Cambiar varios archivos (8)
El siguiente comando está cambiando correctamente el contenido de 2 archivos.
sed -i ''s/abc/xyz/g'' xaa1 xab1
Pero lo que tengo que hacer es cambiar varios de esos archivos dinámicamente y no sé los nombres de los archivos. Quiero escribir un comando que leerá todos los archivos del directorio actual comenzando con xa*
y sed
debería cambiar el contenido del archivo.
Esos comandos no funcionarán en el sed
predeterminado que viene con Mac OS X.
Del man 1 sed
:
-i extension
Edit files in-place, saving backups with the specified
extension. If a zero-length extension is given, no backup
will be saved. It is not recommended to give a zero-length
extension when in-place editing files, as you risk corruption
or partial content in situations where disk space is exhausted, etc.
Intentó
sed -i ''.bak'' ''s/old/new/g'' logfile*
y
for i in logfile*; do sed -i ''.bak'' ''s/old/new/g'' $i; done
Ambos funcionan bien.
Estoy usando find
para una tarea similar. Es bastante simple: tienes que pasarlo como un argumento para sed
como este:
sed -i ''s/EXPRESSION/REPLACEMENT/g'' `find -name "FILE.REGEX"`
De esta manera, no es necesario escribir bucles complejos, y es fácil ver qué archivos va a cambiar, simplemente ejecute find
antes de ejecutar sed
.
Me sorprende que nadie haya mencionado el argumento -exec para encontrarlo, que probablemente sea la forma correcta de hacerlo:
find . -type f -name ''xa*'' -exec sed -i ''s/asd/dsg/g'' {} /;
Alternativamente, uno podría usar xargs, que invocará menos procesos:
find . -type f -name ''xa*'' | xargs sed -i ''s/asd/dsg/g''
Mejor todavía:
for i in xa*; do
sed -i ''s/asd/dfg/g'' $i
done
porque nadie sabe cuántos archivos hay, y es fácil romper los límites de línea de comando.
Esto es lo que sucede cuando hay demasiados archivos:
# grep -c aaa *
-bash: /bin/grep: Argument list too long
# for i in *; do grep -c aaa $i; done
0
... (output skipped)
#
Otra forma más versátil es usar find
:
sed -i ''s/asd/dsg/g'' $(find . -type f -name ''xa*'')
Podrías usar grep y sed juntos. Esto le permite buscar subdirectorios recursivamente.
Linux: grep -r -l <old> * | xargs sed -i ''s/<old>/<new>/g''
OS X: grep -r -l <old> * | xargs sed -i '''' ''s/<old>/<new>/g''
For grep:
-r recursively searches subdirectories
-l prints file names that contain matches
For sed:
-i extension (Note: An argument needs to be provided on OS X)
puedes hacer
'' xxxx '' text u search y lo reemplazará por '' aaaa ''
grep -Rn ''**xxxx**'' /path | awk -F: ''{print $1}'' | xargs sed -i ''s/**xxxx**/**yyyy**/''
@PaulR publicó esto como un comentario, pero las personas deberían verlo como una respuesta (y esta respuesta funciona mejor para mis necesidades):
sed -i ''s/abc/xyz/g'' xa*
Esto funcionará para una cantidad moderada de archivos, probablemente del orden de decenas, pero probablemente no del orden de millones .