find & sed (buscar y reemplazar)

27

Estoy usando el siguiente comando en mi mac:

$find . -name “*.java” -exec sed -i ’s/foo/bar/g’ {} \;

y parece no tener efecto.

Tengo dos archivos en el directorio que terminan en .java, que tienen el texto foo en ellos. ¿Me estoy perdiendo de algo?

EDITAR: Resultados de la solicitud de comentarios

[aafghani-03:~/test amirafghani]$ find . -name "*.java" -exec sed -i 's/foo/bar/g' {} \;
sed: 1: "./bar.java": invalid command code .
sed: 1: "./foo.java": invalid command code .
Amir Afghani
fuente
2
¿Es eso exactamente lo que estás ejecutando? ¿Qué pasa si quitas el -execy todo después? ¿Imprime los nombres de los archivos Java? (Me preocupa que estés usando comillas inteligentes en lugar de comillas ASCII)
Mikel
1
En realidad, eso lo resuelve, al menos para mí. Las comillas dobles y simples deben sustituirse por "y ', respectivamente.
Lev Levitsky
2
Citas inteligentes (?) .. :)
Peter.O
Lo que pegué fue exactamente lo que estaba ejecutando. ¿Alguien puede publicar una respuesta?
Amir Afghani
1
La próxima vez, publique el mensaje de error que ve cuando hace la pregunta. Ahorrará tiempo para todos.
Mikel

Respuestas:

34

En primer lugar, asegúrese de usar comillas ascii regulares como "y '(códigos ascii 0x22y 0x27, respectivamente) en los scripts de shell, porque el ejemplo en su publicación contiene caracteres de comillas no estándar. Si te fijas bien, se ven un poco diferentes. Lo más probable es que se trate de un error de copiar y pegar de un formato de documento de texto enriquecido como Word, OOWriter o incluso una ventana del navegador.

Como estás en una Mac, es probable que tengas la implementación de FreeBSD sed, en cuyo caso debes escribir el comando de esta manera:

find . -name "*.java" -exec sed -i '' s/foo/bar/g {} +

(aquí usando en +lugar de \;evitar ejecutar una sedinvocación por archivo).

En la implementación de FreeBSD, sedel -iindicador necesita un argumento: la extensión de un archivo de respaldo. Por ejemplo, con -i .bakel comando realizaría una copia de seguridad file1.txtcomo file1.txt.bakprimero antes de realizar el reemplazo en el archivo original. Usar un argumento vacío ''significa no usar un archivo de copia de seguridad, que parece ser lo que desea.

Lo mismo en la implementación de GNU (o NetBSD, OpenBSD, busybox) sería:

find . -name "*.java" -exec sed -i s/foo/bar/g {} +

Gracias @bahamat y @Mikel y @ pieter-breed por mejorar mi respuesta con sus comentarios.

Detener el daño continuo a Mónica
fuente
¿Qué hacen las llaves?
Zane Hitchcox
3
@ZaneHitchcox las llaves son marcadores de posición para el nombre de archivo coincidente
Detener el daño continuo a Mónica