Something I find myself doing a lot is running a find command and then editing all of them in vi, which looks something like this:

> find . "*.txt"

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

Is there a clever & simple way to do this all in one command line?

  • 1
    You can pipe it into vi: find . "*.txt" | xargs vi – MaQleod Sep 15 '11 at 15:55
  • 1
    @MaQleod: Technically it would be piping to xargs. – grawity Sep 15 '11 at 16:18
  • Related: Terminal borked after invoking Vim with xargs. – kenorb Nov 16 '17 at 11:49
  • Piping to xargs destroyed my shell terminal. The proper solution is the one below by @DevSolar – typelogic Sep 13 '18 at 14:36

This should do the trick:

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

Use Vim, it's better for your health. :-)

The oft-overlooked + option to -exec makes all filenames (up to line length limits) appear in one line, i.e. you still get all the files opened in one vim session (navigated with :n for next and :N for previous file).

With vim -p you get a file tab for each file. Check :help tab-page-commands for more details.

With vim -o you will get horizontally split windows for each file, vim -O vertically split windows. Check :help window-move-cursor for more details.

Note that the previous version of this answer, vim $(find . -name "*.txt"), does not work with spaces in filenames, and has security implications.

Piping into xargs vi gives a Warning: Input is not from a terminal, plus a terminal with completely bogus behaviour afterwards. User grawity explained why in a comment below, and with a bit more explanation in this question.

  • 4
    Don't know how much you know about vim, but it took me /forever/ to figure out that :n shows the next file and :N shows the previous one. – zpletan Sep 15 '11 at 16:17
  • 4
    @DevSolar: Vim expects its stdin to be the same as its controlling terminal, and performs various terminal-related ioctls on stdin directly. (You could consider this a bug. Vim certainly can open /dev/tty and call ioctl() on that; it's just too lazy to do it.) When invoked by xargs, vim receives /dev/null as its standard input, which just ignores terminal-control ioctls. – grawity Sep 15 '11 at 16:18
  • 3
    @zpletan: vim -p if you want file tabs. (gt and gT to navigate, or click with your mouse.) – grawity Sep 15 '11 at 16:45
  • 2
    FYI, to avoid the warning when piping into vim, just specify - as the first argument, as in echo foobar | vim -. – Konrad Rudolph Sep 15 '11 at 18:47
  • 2
    @Konrad Rudolph: find . -name "*.txt" | vim - gives you a vim session on an unnamed file containing the names of the found files, which is not what the OP asked for... – DevSolar Sep 16 '11 at 7:06

Or run vim and from there:

:args **/*.txt

Additionally, if you wanted them opened one at a time, you can also use find -exec or use a simple for loop. Edited per ceving's comment.

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


IFS=$(echo -en "\n\b")
for i in `find . -name "*.txt"`
        vi $i
  • ...but why would you want to do that? – DevSolar Sep 15 '11 at 16:29
  • @DevSolar The first is to point out the capability in find, the second is a general purpose loop. Maybe you want to do something to every file before you edit it. – OldWolf Sep 15 '11 at 18:12
  • Have you ever tried the second? First: the find returns the current directory because -name is missing. And second: the command fails miserably as soon as a file name contains a space. -1 for ill-advised answer. – ceving Sep 16 '11 at 8:38
  • Actually, the subject of spaces in filenames applies to my answer just as well. I cannot even think of a way to handle them properly without turning it from a command line into a little script of its own. There is a good reason why spaces in filenames are discouraged. – DevSolar Sep 16 '11 at 11:34
  • @ceving A valid point. I presumed the original posters find was valid for his needs. Editing. – OldWolf Sep 16 '11 at 14:01

If you've already typed out your find command I find that it can be much easier to use xargs to open the search results:

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

The -p option tells vim to open each file in a new tab. I find this more convenient than just using buffers, but if you don't then just leave off that option.

  • thank you I connected it to locate so my command was: locate filename | xargs vim -p – talsibony Sep 13 '16 at 8:44

To edit all *.txt, you can just run: vim *.txt. To edit files returned by find, read futher.

On Unix/macOS, you can use find with BSD xargs (see: man xargs), e.g.

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

-o (xargs): Reopen stdin as /dev/tty in the child process before executing the command.

Related: Terminal borked after invoking Vim with xargs at Vim.SE.

protected by JakeGould Oct 14 '15 at 22:00

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.