Execute a command within Vim from the command line

Is there a way to execute a Vim command on a file from the command line?

I know the opposite is true like this:

:!python %

But what if I wanted to :retab a file without opening it in Vim? For example:

> vim myfile.c
:retab | wq

This will open myfile.c, replace the tabs with spaces, and then save and close. I'd like to chain this sequence together to a single command somehow.

It would be something like this:

> vim myfile.c retab | wq

Solution 1:

This works:

gvim -c "set et|retab|wq" foo.txt

set et (= set expandtab) ensures the tab characters get replaced with the correct number of spaces (otherwise, retab won't work).

I don't normally use it, but vim -c ... also works

The solution as given above presumes the default tab stop of eight is appropriate. If, say, a tab stop of four is intended, use the command sequence "set ts=4|set et|retab|wq".

Solution 2:

You have several options:

  • -c "commands" : will play Ex commands as you entered them in the command line.
    In your example : vim myfile -c 'retab | wq'. This is what Firstrock suggested.

  • -S "vim source file" : will source given vim script
    (like running vim -c "source 'vim source file'"):

    If you have a file script.vim containing:

    retab
    wq
    

    Then you can use vim myfile.c -s script.vim (the extension does not really matter)

  • -s "scriptin file": will play contents of file as it contains normal mode commands: If you have script.txt containing:

    :retab
    ZZ
    

    with end of lines consisting of a single ^M character (for example you saved the script using the :set fileformat=mac | w), then you can run: vim myfile.c -S script.txt (ZZ is another way to exit vim and save current file).
    Note that you can record those scripts with vim my_file -W script.txt, but it suffers a bug if you happen to use gvim (the GUI).

Solution 3:

Not a direct answer to your question, but if you want to replace tabs with spaces (or do any other regex search/replace) for a list of files, you can just use in-place sed search/replace:

sed -i 's/\t/   /g' foo1.txt foo2.txt

or

ls *.txt | xargs sed -i 's/\t/   /g'

(In this example I am replacing each tab character with three spaces.)


NOTE: the -i flag means operate in-place.

From the sed man page:

   -i[SUFFIX], --in-place[=SUFFIX]

          edit files in place (makes backup if  extension
          supplied)