Comment puis-je modifier tous les fichiers retournés par find in vi sous Linux?


27

Quelque chose que je me trouve faire souvent est d'exécuter une commande find et de les éditer tous dans vi, qui ressemble à ceci:

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

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

Existe-t-il un moyen intelligent et simple de tout faire en une seule ligne de commande?


1
Vous pouvez le diriger dans vi: find. "* .txt" | xargs vi
MaQleod

1
@MaQleod: Techniquement, ce serait de la tuyauterie vers xargs .
grawity


Tuyauterie pour xargsdétruire mon terminal shell. La solution appropriée est celle ci-dessous par @DevSolar
typelogic

Réponses:


41

Cela devrait faire l'affaire:

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

Utilisez Vim, c'est mieux pour votre santé. :-)

L' +option souvent ignorée pour faire -execapparaître tous les noms de fichiers (jusqu'à des limites de longueur de ligne) sur une seule ligne, c'est-à-dire que vous obtenez toujours tous les fichiers ouverts en une seule vim session (parcourue avec :npour le :Nfichier suivant et le fichier précédent).

Avec vim -pvous obtenez un onglet de fichier pour chaque fichier. Vérifiez :help tab-page-commandspour plus de détails.

Avec vim -ovous obtiendrez des fenêtres divisées horizontalement pour chaque fichier, vim -Odes fenêtres divisées verticalement. Vérifiez :help window-move-cursorpour plus de détails.

Notez que la version précédente de cette réponse vim $(find . -name "*.txt"),, ne fonctionne pas avec les espaces dans les noms de fichiers et a des implications de sécurité.

La tuyauterie dans xargs vidonne un Warning: Input is not from a terminal, plus un terminal avec un comportement complètement faux par la suite. L'utilisateur grawity a expliqué pourquoi dans un commentaire ci-dessous, et avec un peu plus d'explications dans cette question .


4
Je ne sais pas ce que vous savez sur vim, mais il m'a fallu / pour toujours / pour comprendre que: n affiche le fichier suivant et: N affiche le précédent.
zpletan

4
@DevSolar: Vim s'attend à ce que son stdin soit le même que son terminal de contrôle et effectue directement divers ioctls liés au terminal sur stdin. (Vous pouvez considérer cela comme un bogue. Vim peut certainement ouvrir /dev/ttyet appeler ioctl () à ce sujet; c'est juste trop paresseux pour le faire.) Lorsqu'il est appelé par xargs, vim reçoit /dev/nullcomme son entrée standard, qui ignore simplement les ioctls de contrôle de terminal.
grawity

3
@zpletan: vim -psi vous voulez des onglets de fichiers. ( gtet gTpour naviguer, ou cliquez avec votre souris.)
grawity

2
Pour info, pour éviter l'avertissement lors de la canalisation vim, spécifiez simplement -comme premier argument, comme dans echo foobar | vim -.
Konrad Rudolph

2
@Konrad Rudolph: find . -name "*.txt" | vim -vous donne une session vim sur un fichier sans nom contenant les noms des fichiers trouvés, ce qui n'est pas ce que l'OP a demandé ...
DevSolar

4

Ou lancez vim et à partir de là:

:args **/*.txt

1

De plus, si vous souhaitez les ouvrir un à la fois, vous pouvez également utiliser find -exec ou utiliser une boucle for simple. Modifié par le commentaire de la ceving.

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

ou

OLDIFS=$IFS
IFS=$(echo -en "\n\b")
for i in `find . -name "*.txt"`
    do
        vi $i
    done
IFS=$OLDIFS

...Mais pourquoi tu veux faire ça?
DevSolar

@DevSolar Le premier est de souligner la capacité de find, le second est une boucle à usage général. Vous souhaitez peut-être faire quelque chose pour chaque fichier avant de le modifier.
OldWolf du

Avez-vous déjà essayé le second? Premièrement: la recherche renvoie le répertoire courant car il -nameest manquant. Et deuxièmement: la commande échoue lamentablement dès qu'un nom de fichier contient un espace. -1 pour une réponse mal avisée.
ceving

En fait, le sujet des espaces dans les noms de fichiers s'applique également à ma réponse. Je ne peux même pas penser à un moyen de les gérer correctement sans le transformer d'une ligne de commande en un petit script à lui tout seul. Il y a une bonne raison pour laquelle les espaces dans les noms de fichiers sont découragés.
DevSolar

@ceving Un point valide. J'ai présumé que les affiches originales trouvées étaient valables pour ses besoins. Édition.
OldWolf

0

Si vous avez déjà tapé votre findcommande, je trouve qu'il peut être beaucoup plus facile d'utiliser xargspour ouvrir les résultats de la recherche:

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

L' -poption indique à vim d'ouvrir chaque fichier dans un nouvel onglet. Je trouve cela plus pratique que d'utiliser simplement des tampons, mais si vous ne le faites pas, laissez cette option.


merci je l'ai connecté pour localiser donc ma commande était: localiser le nom de fichier | xargs vim -p
talsibony

0

Pour modifier tout *.txt, il vous suffit de lancer: vim *.txt. Pour modifier les fichiers renvoyés par find, lisez la suite.


Sur Unix / macOS, vous pouvez utiliser findavec BSD xargs(voir:) man xargs, par exemple

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

-o( xargs): Rouvrez stdin en tant que / dev / tty dans le processus enfant avant d'exécuter la commande.

Connexes: Terminal borked après avoir appelé Vim avec xargs sur Vim.SE.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.