Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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?

share|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
add comment

3 Answers

up vote 14 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.

share|improve this answer
    
No need to escape the *, globbing won't happen inside the double quotes. –  Kusalananda Sep 15 '11 at 15:57
3  
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

Or run vim and from there:

:args **/*.txt
share|improve this answer
add comment

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
share|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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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