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"
./file1.txt
./file2.txt
./path/to/file3.txt

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

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

link|improve this question
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
feedback

3 Answers

up vote 10 down vote accepted

This should do the trick:

vim $(find . -name "*.txt")

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

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.

link|improve this answer
No need to escape the *, globbing won't happen inside the double quotes. – Kusalananda Sep 15 '11 at 15:57
2  
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
2  
@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
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
1  
@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
show 8 more comments
feedback

Or run vim and from there:

:args **/*.txt
link|improve this answer
feedback

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 {} \;

or

OLDIFS=$IFS
IFS=$(echo -en "\n\b")
for i in `find . -name "*.txt"`
    do
        vi $i
    done
IFS=$OLDIFS
link|improve this answer
...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
feedback

Your Answer

 
or
required, but never shown

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