Necesito hacer un regex buscar y reemplazar en todos los archivos de una carpeta (y sus subcarpetas). ¿Cuál sería el shell de linux comando para hacer eso?

Por ejemplo, quiero correr esta por encima de todos los archivos y sobrescribir el archivo antiguo con el nuevo, sustituye el texto.

sed 's/old text/new text/g' 
InformationsquelleAutor nickf | 2009-05-25

6 Comentarios

  1. 109

    No hay manera de hacerlo usando sólo sed. Usted tendrá que utilizar al menos la utilidad buscar juntos:

    find . -type f -exec sed -i.bak "s/foo/bar/g" {} \;

    Este comando creará un .bak de archivo para cada archivo modificado.

    Notas:

    • La -i argumento para sed comando es una extensión de GNU, por lo que, si se ejecuta este comando con el BSD del sed tendrá que redirigir la salida a un archivo nuevo, a continuación, cambie el nombre.
    • La find utilidad no implementar el -exec argumento en el viejo UNIX cajas, así, usted tendrá que utilizar un | xargs lugar.
  2. 35

    Yo prefiero usar find | xargs cmd más de find -exec porque es más fácil de recordar.

    Este ejemplo a nivel mundial reemplaza a «foo» con «bar» en .archivos txt en o por debajo de su directorio actual:

    find . -type f -name "*.txt" -print0 | xargs -0 sed -i "s/foo/bar/g"

    La -print0 y -0 opciones pueden ser dejados de lado si los nombres no contienen funky personajes como espacios.

    • Si estás en OSX, intente find . -type f -name "*.txt" -print0 | xargs -0 sed -i '' "s/foo/bar/g" (nota proporcionando una cadena vacía para el -i argumento).
  3. 6

    Para la portabilidad, yo no dependen de las características de la sed que son específicas de linux o BSD. En lugar de eso utiliza el overwrite secuencia de comandos de Kernighan y Pike libro sobre el Entorno de Programación Unix.

    El comando es entonces

    find /the/folder -type f -exec overwrite '{}' sed 's/old/new/g' {} ';'

    Y la overwrite script (lo que yo uso todo el lugar) es

    #!/bin/sh
    # overwrite:  copy standard input to output after EOF
    # (final version)
    
    # set -x
    
    case $# in
    0|1)        echo 'Usage: overwrite file cmd [args]' 1>&2; exit 2
    esac
    
    file=$1; shift
    new=/tmp/$$.new; old=/tmp/$$.old
    trap 'rm -f $new; exit 1' 1 2 15    # clean up files
    
    if "[email protected]" >$new               # collect input
    then
        cp $file $old   # save original file
        trap 'trap "" 1 2 15; cp $old $file     # ignore signals
              rm -f $new $old; exit 1' 1 2 15   # during restore
        cp $new $file
    else
        echo "overwrite: $1 failed, $file unchanged" 1>&2
        exit 1
    fi
    rm -f $new $old

    La idea es que se sobrescribe un archivo sólo si el comando se ejecuta correctamente. Útil en find y también donde usted no desea utilizar

    sed 's/old/new/g' file > file  # THIS CODE DOES NOT WORK

    debido a que la cáscara se trunca el archivo antes de sed puede leer.

  4. 1

    Podría sugerir (después de la copia de seguridad de sus archivos):

    find /the/folder -type f -exec sed -ibak 's/old/new/g' {} ';'
  5. -3

    En caso de que el nombre de los archivos en la carpeta de algunos nombres corrientes (como file1, file2…) que he usado para el ciclo.

    for i in {1..10000..100}; do sed 'old\new\g' 'file'$i.xml > 'cfile'$i.xml; done
    • esto no está relacionado con la pregunta. La cuestión no menciona nada sobre el mismo nombre de archivo / carpeta patrón. Por favor, evite tales respuestas

Dejar respuesta

Please enter your comment!
Please enter your name here