¿Cómo puedo editar todos los archivos devueltos por find en vi en Linux?

27

Algo que me encuentro haciendo mucho es ejecutar un comando de búsqueda y luego editarlos en vi, que se parece a esto:

> find . "*.txt"
./file1.txt
./file2.txt
./path/to/file3.txt

> vi ./file1.txt ./file2.txt ./path/to/file3.txt

¿Hay una manera inteligente y simple de hacer todo esto en una sola línea de comando?

abeger
fuente
1
Puedes canalizarlo a vi: find. "* .txt" | xargs vi
MaQleod
1
@MaQleod: Técnicamente sería canalizar a xargs .
Grawity
Tuberías para xargsdestruir mi terminal de shell. La solución adecuada es la siguiente por @DevSolar
typelogic

Respuestas:

41

Esto debería funcionar:

find . -name "*.txt" -exec vim {} + 

Usa Vim, es mejor para tu salud. :-)

La +opción que a menudo se pasa por alto -exechace que todos los nombres de archivo (hasta los límites de longitud de línea) aparezcan en una línea, es decir, todavía se abren todos los archivos en una vim sesión (se navega con el archivo :nsiguiente y el :Nanterior).

Con vim -pusted obtendrá una pestaña de archivo para cada archivo. Consulte :help tab-page-commandspara más detalles.

Con vim -ousted obtendrá ventanas divididas horizontalmente para cada archivo, vim -Oventanas divididas verticalmente. Consulte :help window-move-cursorpara más detalles.

Tenga en cuenta que la versión anterior de esta respuesta, vim $(find . -name "*.txt")no funciona con espacios en los nombres de archivo y tiene implicaciones de seguridad.

Tubería en xargs vida un Warning: Input is not from a terminal, además de un terminal con un comportamiento completamente falso después. La gravedad del usuario explicó por qué en un comentario a continuación, y con un poco más de explicación en esta pregunta .

DevSolar
fuente
44
No sé cuánto sabe sobre vim, pero me llevó / para siempre / descubrir que: n muestra el siguiente archivo y: N muestra el anterior.
zpletan
44
@DevSolar: Vim espera que su stdin sea el mismo que su terminal de control, y realiza varios ioctls relacionados con el terminal en stdin directamente. (Podría considerar esto como un error. Vim ciertamente puede abrirse /dev/ttyy llamar a ioctl () sobre eso; es demasiado flojo para hacerlo.) Cuando es invocado por xargs, vim recibe /dev/nullcomo su entrada estándar, lo que simplemente ignora los ioctls de control de terminal.
Grawity
3
@zpletan: vim -psi quieres pestañas de archivo. ( gty gTpara navegar o hacer clic con el mouse)
Grawity
2
Para su información, para evitar la advertencia al conectarse vim, simplemente especifique -como primer argumento, como en echo foobar | vim -.
Konrad Rudolph
2
@Konrad Rudolph: find . -name "*.txt" | vim -le ofrece una sesión vim en un archivo sin nombre que contiene los nombres de los archivos encontrados, que no es lo que solicitó el OP ...
DevSolar
4

O ejecuta vim y desde allí:

:args **/*.txt
Benoit
fuente
1

Además, si desea que se abran uno a la vez, también puede usar find -exec o usar un bucle for simple. Editado por el comentario de ceving.

find . -name "*.txt" -exec vi {} \;

o

OLDIFS=$IFS
IFS=$(echo -en "\n\b")
for i in `find . -name "*.txt"`
    do
        vi $i
    done
IFS=$OLDIFS
OldWolf
fuente
... pero ¿por qué quieres hacer eso?
DevSolar
@DevSolar El primero es señalar la capacidad en find, el segundo es un bucle de propósito general. Tal vez quiera hacer algo a cada archivo antes de editarlo.
OldWolf
¿Alguna vez has probado el segundo? Primero: el resultado devuelve el directorio actual porque -namefalta. Y segundo: el comando falla miserablemente en cuanto un nombre de archivo contiene un espacio. -1 por respuesta desacertada.
ceving
En realidad, el tema de los espacios en los nombres de archivo también se aplica a mi respuesta. Ni siquiera puedo pensar en una forma de manejarlos adecuadamente sin convertirlo de una línea de comando en un pequeño script propio. Hay una buena razón por la cual se desaconsejan los espacios en los nombres de archivo.
DevSolar
@ceving Un punto válido. Supuse que el póster original encontrado era válido para sus necesidades. Edición.
OldWolf
0

Si ya escribió su findcomando, encuentro que puede ser mucho más fácil de usar xargspara abrir los resultados de búsqueda:

find . -name "*.txt" | xargs vim -p

La -popción le dice a vim que abra cada archivo en una nueva pestaña. Creo que esto es más conveniente que solo usar buffers, pero si no lo hace, simplemente deje esa opción.

Cory Klein
fuente
gracias Lo conecté para localizar, así que mi comando fue: localizar nombre de archivo | xargs vim -p
talsibony
0

Para editar todo *.txt, sólo puede ejecutar: vim *.txt. Para editar archivos devueltos por find, lea más adelante.


En Unix / macOS, puede usarlo findcon BSD xargs(consulte :) man xargs, p. Ej.

find -L . -name "*.txt" -type f -print0 | xargs -o -0 vim

-o( xargs): Vuelva a abrir stdin como / dev / tty en el proceso secundario antes de ejecutar el comando.

Relacionado: Terminal borked después de invocar a Vim con xargs en Vim.SE.

kenorb
fuente