I often want to run multiple
vim commands on multiple files.
Consider the files
file3.txt: I might want to run
:retab and then some
:%s/ /, / for instance.
How can I "pipe" this through Vim?
Vi and Vim Stack Exchange is a question and answer site for people using the vi and Vim families of text editors. It only takes a minute to sign up.Sign up to join this community
First, you are running Vim, not Vi, because the latter does not offer the
Assuming the file should be modified (that is what
x does below), you can pipe the commands to Ex improved mode this way:
printf '%s\n' 'retab' '%s/ /, /' 'x' | vim -E file1.txt
Now, bear in mind that Ex will skip your
retab will not take
expandtab values from that file. Of course, you can just manually supply them, for example,
printf '%s\n' 'set expandtab' 'retab' '%s/ /, /' 'x' | vim -E file1.txt
To operate on various files (matching
file[digit].txt), just wrap it in a shell loop,
for file in file[0-9].txt; do printf '%s\n' 'set expandtab' 'retab' '%s/ /, /' 'x' | vim -E "$file" done
You can use the
-c argument in the command-line to run commands in Vim after opening a file. You can pass it multiple times to run the several separate commands. Once you run the editing commands, you'll probably want to include a
:wq to have Vim save your changes and quit.
$ vim -c 'retab' -c '%s/ /, /' -c 'wq' file1.txt
You can of course use that inside a
for loop to run it on each of your text files.
Another option is to open all the files in Vim and then use
:argdo to run a sequence of commands in all the files in the argument list. In that case, you should join all your commands using
| (which is the command separator in Vim) and you should end each
:argdo with an
:update so that it will save the file (if necessary) before proceeding to the next one. This is important, otherwise Vim might refuse to move away from the current buffer, which would break your
$ vim file*.txt
Then inside Vim:
:argdo retab | %s/ /, / | update
All your files will have been updated and you'll be in the last file in your argument list. At this point you can simply quit Vim with
A trivial way without complex commands is to use recording and replays (
help q and
$ vim file1.txt file2.txt file3.txt # (Now you should be seeing contents of `file1.txt`)
qsince it refers to a register, but
recording @qin the status line. Any subsequent operations will be recorded to
:%s/ /,/. The recording mechanism will save these operations to the register
qso you may replay it in the future.
file1.txt, and goto the next file with
q. Now in
qcontains commands to execute your modifications and go to the next file.
@q. You should see the modifications being made to
file2.txtand finally going to
@quntil you see
E165: Cannot go beyond last file, that's when the job's done.