I'm recently working on a project in vim, and I need to execute the same command to different files which are in the same folder in command-line mode multiple times.
like
:%s/V1/V2/g
Is there a easiler way to do this?
It's command-line mode, not "command mode".
From within Vim
Set your :help argument-list to the desired list of files:
:arg /path/to/dir/*.xyz
Perform your substitution on every file in the argument list and write it if there was a change:
:argdo %s/V1/V2/g | update
See :help :arg, :help :argdo, :help :update.
From your shell
Start Vim with each desired file as argument:
$ vim /path/to/dir/*.xyz
Perform your substitution on every file in the argument list and write it if there was a change:
:argdo %s/V1/V2/g | update
How can I paste the contents of the system clipboard to all files in the argument list in Vim?
You can do the following:
:argdo execute 'normal! "+p' | w
Explanation:
:argdo Run the command that follows on each file in the argument list. Alternatively, you can use :windo to run a command on each window, or :bufdo to run a command on each buffer.
execute "normal! ..." Run the sequence of commands after normal! as if they were entered in normal mode. Ignore all mappings and replace string escape sequences like \<esc>.
"+p Paste the register for the system clipboard. Note that Vim has to be compiled with the +clipboard feature enabled for this to work.
| w Write every file, whether it was updated or not. Alternatively, use | update to only write files that were changed.
For more details, see:
Learn Vimscript the Hard Way
Vim 101: Search and Replace on Multiple Files
Run a command in multiple buffers
Originally answered by Roberto Balejík
How can you execute a command again listed in the
:history
option in vim. There are numbers shown. Is the only way to copy the command by hand, then re-enter it? Or is there something like in shell script.
:history is only there for you to look at it.
To re-execute a previous command, you have two options:
Use <Up> and <Down> at the command prompt:
:m10
(do stuff)
:<Up>
Use the "command-line window":
You can call it with q: and navigate with search and use the beautiful normal mode commands we all love.
Position the cursor on a line and hit <CR> to re-execute the command.
Edit a command and hit <CR> to execute the new command.
You can quit the command-line window with :q.
See :help cmdline-window.
I use q: shortcut in normal mode to open interactive command history window. You just move to the right command and execute it by pressing Enter. You can find more information and other ways of accessing history here.
What I like to do is type the first few characters in the command and press <UP>. For example if you want to repeat an edit command of the file file.txt you could:
:e fil<UP><ENTER>
If the first <UP> does not give you the command you want, keep pressing<UP> until you find the command you were looking for.
If Vim is compiled with +eval you can use histget( {history} [, {index}])
:exe histget('c', 15)
That isn't exactly convenient to type, so you can also create a user-defined command:
:com -nargs=1 HI exe histget('c', <args>)
Thereafter you can use HI {index} to execute the history entry:
:HI 15
is there a way to use vim/vi in the vim command line? Sometimes I write a long
command in vim such as:
:!./script /home/user/pet --flag=1
and I want to change for instance "user" by "other". What I usually do is to
navigate the command line with right arrow which is time consuming and even more
when I want to go to the beginning of the line. I would like to have something
like "0" to go there or w/b to move by words. Or use j/k to go to the next/previous
command.
Thanks.
:h cedit
in command line, type ctrl-F(default) to enter command window.
or in normal mode type q:
(for search, type q/)
Vim has a feature called the "commandline window". You can enter it with Control-F by default when you're already on the commandline, or q: from normal mode, edit the commandline using vim commands, and press enter to execute. It also contains your command history so that you can yank previous commands if you like. See :help cmdline-window for more information.
I'm not aware how you can use Vim commands to edit a command directly on the command line, but if you enter the command window q: you get can use regular Vim editing to edit commands.
From there you can execute commands by hitting <CR> or use Ctrl-C to copy the command to the regular command line.
If you run set -o vi you will have vim capabilities in your command line. Just put 'set -o vi' in your .bashrc file or equivalent to have it by default.
Say I'm editing my _vimrc file and I've just added a couple of lines, for instance a new key mapping. I don't want to reload the whole file (:so %) since that will reset a lot of temporary stuff I'm experimenting with. I just want to run the two lines that I'm currently working on.
I'm having no luck trying to copy/paste the lines into the command buffer, since I can't use the put command in there. Is there any way I could run the current line (or current selection) as EX commands?
Summary:
After Anton Kovalenko's answer and Peter Rincker's comment I ended up with these key maps, which either executes the current line, or the current selected lines if in visual mode:
" Execute current line or current selection as Vim EX commands.
nnoremap <F2> :exe getline(".")<CR>
vnoremap <F2> :<C-w>exe join(getline("'<","'>"),'<Bar>')<CR>
To execute the current line as an ex command, you may also use:
yy:#"
This will yank the current line to the "-register and execute it. I don't think it is too much typing.
Executing the line under cursor as an Ex command:
:execute getline(".")
Convenient enough for 2 lines. (I'd figure out something for doing it with regions, but I'm not a vim user). And for currently selected region, the following seems to do the job:
:execute getreg("*")
As commented by Peter Rincker, this mapping can be used for executing the currently selected lines:
:vnoremap <f2> :<c-u>exe join(getline("'<","'>"),'<bar>')<cr>
For that purpose, I have defined the following commands and mappings:
":[range]Execute Execute text lines as ex commands.
" Handles |line-continuation|.
" The same can be achieved via "zyy#z (or yy#" through the unnamed register);
" but there, the ex command must be preceded by a colon (i.e. :ex)
command! -bar -range Execute silent <line1>,<line2>yank z | let #z = substitute(#z, '\n\s*\\', '', 'g') | #z
" [count]<Leader>e Execute current [count] line(s) as ex commands, then
" {Visual}<Leader>e jump to the following line (to allow speedy sequential
" execution of multiple lines).
nnoremap <silent> <Leader>e :Execute<Bar>execute 'normal! ' . v:count1 . 'j'<CR>
xnoremap <silent> <Leader>e :Execute<Bar>execute 'normal! ' . v:count1 . 'j'<CR>
Just after posting this, I found a work-around. I can copy text into the clipboard using "*y, then put that text into the command buffer by using the middle mouse button. This works for me, but is hardly a convenient solution for people without clipboard support, mouse support or just an aversion to removing their hands from the Vim position.
The accepted answer doesn't handle continuation sections. Also, surprisingly, the bar isn't needed, newlines are fine. This will work, first yanking the text into register x:
vno <c-x> "xy:exe substitute(#x,"\n\\",'','g')<cr>
As someone has already mentioned, the only exception are commands that "eat up" newlines. Eg, executing the above mapping on:
:sign define piet text=>> texthl=Search
:exe ":sign place 2 line=23 name=piet file=" . expand("%:p")
will cause vim to to think that the user is trying to define textl as "Search\n:exe ":sign place... etc.
You could also try
:<C-R><C-L><CR>
Per the vim docs, the combination will plop the current line into the command line. From there, hitting enter should do the trick. I realize that this does not handle multiline cases, however it doesn't require a .vimrc and therefore works out of the box.
If you're doing a lot of experimenting (trying things out that you might want to add to your vimrc, I assume?) it might help to do so in a scratch file like experimental.vim so you aren't just relying on your history to know what you're trying out. Now that you have these great mappings, it will be easy to rerun things from experimental or vimrc without sourcing the whole file.
Also (sorry, I can't comment on answers yet, it seems), I tried this mapping of Peter's:
vnoremap <Leader>es :<c-u>exec join(getline("'<","'>"),'<BAR>')<CR>
This works in most cases, but it fails specifically on function definitions.
function! TestMe()
echo "Yay!"
endfunction
This mapping joins the lines into a single string, separated by <BAR> and then execs them.
I'm not entirely sure why, but if I try to do that with a function definition in normal mode:
:exec 'function! TestMe()| echo "Yay!"|endfunction'
-> E488: Trailing characters
After some testing, I've found that it will work with newline separators instead:
:exec "function! TestMe()\n echo 'Yay!'\nendfunction"
:call TestMe()
-> Yay!
So, I've changed my mapping to this:
vnoremap <Leader>es :<c-u>exec join(getline("'<","'>"),"\n")<CR>
I suppose there is a vim or ex reason why the <BAR> method doesn't work on functions (maybe even some setting I have on?), and I'm curious to hear what it is if someone knows.
I don't want to reload the whole file (:so %) since that will reset a lot of temporary stuff I'm experimenting. I just want to run the two lines that I'm currently working on.
If you want to execute a command because you want to refine it before committing it to _.vimrc, then you should launch a Command Line Window for Ex-mode commands with q:.
At launch the Command Line Window is buffered with the contents of the command line history. It is a normal Vim window the contents of which can be edited as any text buffer with the exception of pressing on any line which executes the command on that line. It is very useful when you want to slightly change a long, complex command you wrote earlier and re-run it.
To launch a 'Command Line Window' for search strings press q/.
!! (shorthand for :.!) executes the current line as input to a command, per POSIX ex & vi. You may need to append sh if it is a system command.
Executing !! on a blank line (and omitting sh) is a shortcut for reading a shell command straight into the buffer. By it's nature :.! overwrites the current line while :.r! inserts on the line below.
ls -A | head -n +4
~
~
!sh
Results:
.sh_history
.sh_logout
.kshrc
corelist.txt
~
~
4 lines added; 1 line deleted`
This means there is no need to redirect pipelines to a file and then examine the data to see if the contents are valid. Just execute commands in vi directly and undo if you make a mistake.
Alternately, yanking a line as a named buffer allows you to execute it as an ex command, almost like a macro. You can still edit and undo the line to get it correct instead of trying to edit the : line in command mode.
The functions recommended here are all POSIX and have been supported for over 40 years, so no special vim or other enhanced features are required.
:%s/meep/pEEp/ | g/foo/ s//BAR
foo
grok
meep
~
~
Yank the ex command (line 1, :%s...) into a named buffer / macro.
I just use the label m for "macro".
"myy
or
:1y m
Now execute the named buffer / macro, in command mode, using #:
#m
Results:
:%s/pEEp/pEEp/ | g/BAR / s//BAR
BAR
grok
pEEp
~
~
4 lines changed
But remember that "multiple undo" is not POSIX. undo is only a toggle between undo and redo in a "historically accurate & compliant" ex / vi implementation.
The work-around is to save to a temporary (or valid) file name before executing a questionable edit:
:w $$.tmp
Then just :e! to "reset and reload" if needed.
You can also use :pre (preserve) to make a special temporary backup file prior to making multiple changes.
Then use :reco! % (recover this!) to restore back to that point.
Realize that :preserve creates a snapshot-like file which is deleted as soon as it is rolled back to. It does not matter if you save the edit(s) or not.
Therefore writing your own file (:w ...) and restoring with :e! may still have value because the system will not automatically delete it.
:pre is perfect when you should have ran sudo vi ... or otherwise do not have the necessary permissions - but you only realized the mistake after making several changes. i.e. vi /etc/sudoers instead of sudo vi /etc/sudoers.
^^ NEVER DO THIS! ONLY AN EXAMPLE! USE sudo visudo INSTEAD!
You can get a list of existing recovery files with vi -r and recover one directly with vi -r filename as needed, optionally with something like sudo vi -r filename.
The distinction here is that even though the ":preserved file" has it's own "special" name and path internally, it will :write to the original, intended location when ":recovered ==> /etc/sudoers
Just be sure to use :wq! and not something like ZZ when done with your "recovery" or you will still lose the edits which you tried to save.
By the way, ^R is expected to redraw or repaint the display per POSIX; it is not "undo" in any compliant vi implementation.