21

Let's say I have a function, named StripWhitespace.

I can run it on a single file by opening the file and running :StripWhitespace.

How can I automatically run that function against a folder of files, and save the results as I go along?

200_success
  • 9,549
  • 5
  • 51
  • 64
squarefrog
  • 895
  • 1
  • 7
  • 10

2 Answers2

24

If you are already in Vim, you can use the :argdo or :bufdo commands to execute a command on every item in the argument list or buffer list, respectively.

e.g. to run a : command on every file in the argument list:

:argdo StripWhitespace

Or to invoke a function from every file in the buffer list:

:bufdo call StripWhitespace()

Or to run macro q on every file in the arguments list:

:argdo normal @q

You can then save all changed buffers with :wall, or save all and quit Vim with :wqall.

If you want to write the files as you go along, you can add in a call to :update, like so:

:argdo s/foo/bar/ge | update

There are various ways you can get the files into Vim in the first place, including:

  • Supply parameters to the vim command line: vim * (this adds all the files to the argument list),
  • Use the :args command (which supports wildcards and backtick expressions) to populate the argument list, or the :argadd command to add files to it,
  • Just open them all manually with :e, :Ex, or a file-opening plugin.
Rich
  • 31,891
  • 3
  • 72
  • 139
  • 2
    I like this answer because it doesn't require leaving Vim, which in my opinion is too expensive (my precious buffer list!). I have some notes: (1) leaving buffers without writing requires 'hidden' to be set; (2) the : update command is a slight improvement over :w because it only writes if a change has been made, so :bufdo update or :argdo update will write all modified buffers or arguments. – tommcdo Feb 12 '15 at 11:10
  • Good point on update. I considered mentioning hidden when I was writing the answer, but decided against it because I didn't want to overcomplicate it. On reflection though, it should be in there. I'll update the answer to include both suggestions presently. – Rich Feb 12 '15 at 11:18
  • @tommcdo Just checked the documentation for :wall, and it only writes changed buffers, so :bufdo update is not necessary after all. – Rich Feb 12 '15 at 11:20
  • good catch regarding :wall, which also has the advantage of not cycling through buffers and moving you away from where you started. I suppose :argdo update is still a different story -- maybe you don't want to write to buffers that are not in your argument list. – tommcdo Feb 12 '15 at 11:44
  • @tommcdo Good point. – Rich Feb 12 '15 at 11:45
  • Would be great to add silent! at the beginning for sake of speed! – SergioAraujo Aug 25 '21 at 19:25
14

You can use the -c argument to run a command on startup, from vim(1):

   -c {command}
               {command} will be executed after the first  file  has  been
               read.   {command}  is interpreted as an Ex command.  If the
               {command} contains spaces it must  be  enclosed  in  double
               quotes  (this depends on the shell that is used).  Example:
               Vim "+set si" main.c
               Note: You can use up to 10 "+" or "-c" commands.

Example:

vim -c ':call StripWhitespace()' file1 file2

To quit afterwards, add | :wqa:

vim -c ':call StripWhitespace() | :wqa' file1 file2
Martin Tournoij
  • 62,054
  • 25
  • 192
  • 271