Adding a simple line to my .vimrc I managed to open an ePub archive with zip.vim on a vim buffer. This basically opens a numbered list of htm, css, jpg, xml files that one can access individually. I want to perform a search and replace through all these numbered files as it is too painful to edit each of them and do it - there's around 400 files. :args and :argdo did not really work or at least I could not make them. Any ideas?
I'm not sure it will work for you, and I'm going to assume that when you hit Enter on a filepath inside your Vim buffer, a new viewport is opened (by the ZipBrowseSelect()
function defined in $VIMRUNTIME/autoload/zip.vim
) to display the contents of the file.
If this is the case, you could try the following method.
:%argd
This command deletes all the paths in the current arglist.
Then, you would have to visually select all the lines containing a path to a file you want to modify. From normal mode, you could hit vip
, for example, and adjust the visual selection to exclude some lines if needed.
:'<,'>g/^/exe "norm \r" | argadd % | close
This command should hit Enter on each line inside your visual selection, add the file which has been opened in a new viewport, and close the latter to get back to the original window.
:vim /pattern/ ##
This command should populate the quickfix list with all the lines containing the pattern you're looking for.
:cfdo %s/pattern/replacement/ge | update
This command should replace pattern
with replacement
in each file present in the quickfix list, and save the file if it has been changed.
The last step uses the :cfdo
command which was introduced in Vim version 7.4.858. If your Vim version is not new enough to support :cfdo
, you could bypass the last 2 steps, and directly execute:
:argdo %s/pattern/replacement/ge | update
The benefit of:
:vim /pattern/ ##
:cfdo %s/pattern/replacement/ge | update
... is to prune the arglist from the files which don't contain your pattern, so that the substitutions commands are only executed when needed.
If you don't have :cfdo
but still want to prune the arglist, you could source this custom command:
com! -nargs=0 -bar Qargs exe 'args '.s:qfl_names()
fu! s:qfl_names() abort
let buffer_numbers = {}
for qf_item in getqflist()
let buffer_numbers[qf_item['bufnr']] = bufname(qf_item['bufnr'])
endfor
return join(map(values(buffer_numbers), 'fnameescape(v:val)'))
endfu
I've copied it from this video: Project-wide find and replace. Most of the other commands are also taken from this video, so it might help you to have a look at it, if you don't have already.
Then, you would replace the :cfdo
command, with:
:Qargs
:argdo %s/pattern/replacement/ge | update
To summarize, you could try one of these 3 methods:
:%argd
visually select the paths of the files
:'<,'>g/^/exe "norm \r" | argadd % | close
:argdo %s/pattern/replacement/ge | update
Or:
:%argd
visually select the paths of the files
:'<,'>g/^/exe "norm \r" | argadd % | close
:vim /pattern/ ##
:cfdo %s/pattern/replacement/ge | update
Or:
:%argd
visually select the paths of the files
:'<,'>g/^/exe "norm \r" | argadd % | close
:vim /pattern/ ##
:Qargs
:argdo %s/pattern/replacement/ge | update
Edit:
You could also try to visually select the paths of the files, then execute:
:'<,'>g/^/e `='zipfile:'.expand('%:p').'::'.getline(".")` | %s/pattern/replacement/ge | update | b#
This method relies on the fact that the path to a file in the archive seems to follow this scheme:
zipfile:/path/to/epub::path/to/file/in/archive
So, you can get the path to a file under the cursor with the Vim expression:
'zipfile:'.expand('%:p').'::'.getline(".")
And you can edit this file using backticks (see :h `=
):
:e `=Vim expression`
→
:e `='zipfile:'.expand('%:p').'::'.getline(".")`
From there, you need the global command, to repeat the edition on each line inside the visual selection.
In the epub I tested, all the paths were below the line mimetype
. If this is the case for you, then you could merge the 2 steps (visual selection + global command) in a single command:
1/mimetype/+,$g/^/e `='zipfile:'.expand('%:p').'::'.getline(".")` | %s/pattern/replacement/ge | update | b#