Come posso modificare tutti i file restituiti da find in vi in ​​Linux?


27

Qualcosa che mi trovo a fare molto è l'esecuzione di un comando find e quindi la modifica di tutti in vi, che assomiglia a questo:

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

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

C'è un modo intelligente e semplice per farlo tutto in una riga di comando?


1
Puoi inserirlo in vi: find. "* .txt" | xargs vi
MaQleod,

1
@MaQleod: tecnicamente sarebbe il piping su xargs .
Grawity,


Tubazioni per xargsdistruggere il mio terminale shell. La soluzione corretta è quella qui sotto di @DevSolar
typelogic

Risposte:


41

Questo dovrebbe fare il trucco:

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

Usa Vim, è meglio per la tua salute. :-)

L' +opzione spesso trascurata per far -execapparire tutti i nomi di file (fino ai limiti di lunghezza della riga) in una riga, ovvero ottenere comunque tutti i file aperti in una vim sessione (navigato con :nper il file successivo e :Nper quello precedente).

Con vim -pte ottieni una scheda file per ogni file. Controlla :help tab-page-commandsper maggiori dettagli.

Con vim -oquesto otterrai finestre divise orizzontalmente per ogni file, vim -Ofinestre divise verticalmente. Controlla :help window-move-cursorper maggiori dettagli.

Si noti che la versione precedente di questa risposta, vim $(find . -name "*.txt")non funziona con spazi nei nomi di file e ha implicazioni di sicurezza.

Il piping in xargs vidà a Warning: Input is not from a terminal, oltre a un terminale con comportamento completamente falso in seguito. La gravità dell'utente ha spiegato perché in un commento di seguito e con un po 'più di spiegazione in questa domanda .


4
Non so quanto sai di vim, ma mi ci è voluto / per sempre / per capire che: n mostra il file successivo e: N mostra il precedente.
zpletan,

4
@DevSolar: Vim prevede che il suo stdin sia lo stesso del suo terminale di controllo ed esegue direttamente vari ioctl relativi al terminale su stdin. (Potresti considerarlo un bug. Vim certamente può aprire /dev/ttye chiamare ioctl () su questo; è semplicemente troppo pigro per farlo.) Quando viene invocato da xargs, vim riceve /dev/nullcome input standard, che ignora semplicemente gli ioctls di controllo del terminale.
Grawity,

3
@zpletan: vim -pse vuoi le schede dei file. ( gte gTper navigare o fare clic con il mouse.)
Grawity

2
Cordiali saluti, per evitare l'avvertimento durante il piping in vim, basta specificare -come primo argomento, come in echo foobar | vim -.
Konrad Rudolph,

2
@Konrad Rudolph: find . -name "*.txt" | vim -ti dà una sessione vim su un file senza nome contenente i nomi dei file trovati, che non è quello che l'OP ha richiesto ...
DevSolar


1

Inoltre, se desideri che vengano aperti uno alla volta, puoi anche utilizzare find -exec o un semplice ciclo for. Modificato per il commento di 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

... ma perché vorresti farlo?
DevSolar,

@DevSolar Il primo è quello di evidenziare la capacità di find, il secondo è un ciclo generico. Forse vuoi fare qualcosa per ogni file prima di modificarlo.
OldWolf,

Hai mai provato il secondo? Primo: la ricerca restituisce la directory corrente perché -namemanca. E secondo: il comando fallisce miseramente non appena il nome di un file contiene uno spazio. -1 per risposta sconsigliata.
ceving il

In realtà, l'argomento degli spazi nei nomi dei file si applica anche alla mia risposta. Non riesco nemmeno a pensare a un modo per gestirli correttamente senza trasformarlo da una riga di comando in un piccolo script a sé stante. C'è una buona ragione per cui gli spazi nei nomi dei file sono scoraggiati.
DevSolar,

@ceving Un punto valido. Presumevo che i manifesti originali fossero validi per le sue esigenze. La modifica.
OldWolf,

0

Se hai già digitato il tuo findcomando, trovo che può essere molto più facile da usare xargsper aprire i risultati della ricerca:

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

L' -popzione dice a vim di aprire ogni file in una nuova scheda. Trovo questo più conveniente del semplice utilizzo dei buffer, ma se non lo fai, lascia perdere questa opzione.


grazie l'ho collegato per individuare quindi il mio comando era: individuare nome file | xargs vim -p
talsibony,

0

Per modificare tutto *.txt, si può semplicemente eseguire: vim *.txt. Per modificare i file restituiti da find, leggi di più.


Su Unix / macOS, puoi usare findcon BSD xargs(vedi :) man xargs, ad es

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

-o( xargs): Riapri stdin come / dev / tty nel processo figlio prima di eseguire il comando.

Correlati: Terminale bloccato dopo aver richiamato Vim con xargs su Vim.SE.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.