سؤال

I have four text files A.txt, B.txt, C.txt and D.txt I have to perform a series of vim editing in all these files. Currently how I am doing is open each files and do the same vim commands one by one.

Is it possible to make a script file which I can run from the command prompt, means without open the actual file for vim editing.

for example, if I have to perform the below vim commands after opening the A.txt file in vim editor:

:g/^\s*$/d
:%s/^/[/
:%s/\(.*\)\(\s\+\)\(.*\)/\3\2\1
:%s/$/]/
:%s/design/test/

Is it possible to make a script file and put all these commands including gvim A.txt (first command in the file). and edit run the script file from command prompt.

If it is possible, please let me know how to do it and how it can be done with single or multiple files at a time?

هل كانت مفيدة؟

المحلول

vim -c <command> Execute <command> after loading the first file

Does what you describe, but you'll have to do it one file at a time.

So, in a windows shell...

for %a in (A,B,C,D) do vim -c ":g/^\s*$/d" -c "<another command>" %a.txt

POSIX shells are similar, but I don't have a machine in front of me at the moment.

I imagine you could load all the files at once and do it, but it would require repeating the commands on the vim command line for each file, similar to

vim -c "<command>" -c "<command>" -c ":n" (repeat the previous -c commands for each file.)  <filenames go here>

EDIT: June 08 2014: Just an FYI, I discovered this a few minutes ago.

vim has the command bufdo to do things to each buffer (file) loaded in the editor. Look at the docs for the bufdo command. In vim, :help bufdo

نصائح أخرى

The amount of -c commands directly passed to Vim on the command-line is limited to 10, and this is not very readable. Alternatively, you can put the commands into a separate script and pass that to Vim. Here's how:

Silent Batch Mode

For very simple text processing (i.e. using Vim like an enhanced 'sed' or 'awk', maybe just benefitting from the enhanced regular expressions in a :substitute command), use Ex-mode.

REM Windows
call vim -N -u NONE -n -es -S "commands.ex" "filespec"

Note: silent batch mode (:help -s-ex) messes up the Windows console, so you may have to do a cls to clean up after the Vim run.

# Unix
vim -T dumb --noplugin -n -es -S "commands.ex" "filespec"

Attention: Vim will hang waiting for input if the "commands.ex" file doesn't exist; better check beforehand for its existence! Alternatively, Vim can read the commands from stdin. You can also fill a new buffer with text read from stdin, and read commands from stderr if you use the - argument.

Full Automation

For more advanced processing involving multiple windows, and real automation of Vim (where you might interact with the user or leave Vim running to let the user take over), use:

vim -N -u NONE -n -c "set nomore" -S "commands.vim" "filespec"

Here's a summary of the used arguments:

-T dumb           Avoids errors in case the terminal detection goes wrong.
-N -u NONE        Do not load vimrc and plugins, alternatively:
--noplugin        Do not load plugins.
-n                No swapfile.
-es               Ex mode + silent batch mode -s-ex
                Attention: Must be given in that order!
-S ...            Source script.
-c 'set nomore'   Suppress the more-prompt when the screen is filled
                with messages or output to avoid blocking.

With all the commands you want to run on each file saved in a script, say "script.vim", you can execute that script on one file like this (as others have mentioned):

vim -c "source script.vim" A.txt

Taking this one step further, you can save your file at the end of the script, either by putting a :w command inside the script itself, or passing it from the command-line:

vim -c "source script.vim | w" A.txt

Now, you can run any command in Vim on multiple files, by using the argdo command. So your command turns into:

vim -c "argdo source script.vim | w" A.txt B.txt C.txt D.txt

Finally, if you want to quit Vim after running your script on every file, just add another command to quit:

vim -c "argdo source script.vim | w" -c "qa" A.txt B.txt C.txt D.txt

Try the following syntax:

ex foo.txt <<-EOF
  g/^\s*$/d
  %s/^/[/
  %s/\(.*\)\(\s\+\)\(.*\)/\3\2\1
  %s/$/]/
  %s/design/test/
  wq " Update changes and quit.
EOF

The ex command is equivalent to vim -E. Add -V1 for verbose output.

Alternative one-liner syntax is for example:

ex +"g/^\s*$/d" +"%s/^/[/" +"%s/design/test/" -cwq foo.txt

To load commands from the file, use -s cmds.vim.

You can also use shebang for Vim to parse the file from the argument.

For more examples, see:

JimR and Ingo have provided excellent answers for your use case.

Just to add one more way to do it, however, you could use my vimrunner plugin to script the interaction in ruby: https://github.com/AndrewRadev/vimrunner.

Example:

vim = Vimrunner.start

vim.edit "file.txt"
vim.insert "Hello"
vim.write

vim.kill

This can be useful for more complicated interactions, since you get the full power of a programming language.

Use vim -s ... to script not only colon commands, but also normal-mode commands such as = for formatting:

  1. Create a file with all keystrokes that you want vim to execute.
  2. Run vim -s SCRIPT-FILE FILE-TO-EDIT

For example: Let's say you want to use vim's = command to re-indent all the lines of myfile.html. First, using vim itself, make a file named myscript that has this:

gg=G:wq

(gg moves to the top of the file; =G re-indents from the current location to the end of the file; :wq<Enter> saves the file and exits.)

Then, run this to have vim launch, edit myfile.html, and save it:

vim -s myscript myfile.html
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top