I have a shell script on a line alone in a file which I would like to be able to easily execute from vim. Normally I could simply use Y:!^R", but this particular script has % in it, which is expanded to the current filename.

  • Y:exe '!'.@" still treats % as a filename
  • Y:!=getreg('"')` is passed literally

Ideally whatever solution would be trivial to type, like Y:!^R". My current workaround is to run Y:!^R" and then manually insert a \ before each %, but this is work the computer should be responsible for.

The command I'm wanting to run is: expr (expr (date --utc +%s) / 86400 - 7) % 15 + 1 in fish; in bash that would be expr $(expr $(date --utc +%s) / 86400 - 7) % 15 + 1.

Is there an easy way to escape special characters in an ex shell command, or treat what is typed strictly literally? I'm sure vim has this covered, but I've searched a while and don't know how to find it.


One way to do this is to use fnameescape:


But it may not be perfect if the command has spaces. You could also try split(@")->map('fnameescape(v:val)')->join(' ') in the expression, or some combination of shellescape()/escape(…, '%#'), etc.

  • Ironically, Y:!<C-r>=fnameescape(@")<CR> escapes all the spaces, but does not escape the %s. Your second example w/split/map/join does work.
    – Iiridayn
    Jun 16 at 22:38

Possible answer derived from https://vi.stackexchange.com/a/10211/8846 - doesn't function in quite the same way, but :.w !fish does send the text to a new shell literally and returns the correct answer.

It also makes it easier to write short python or other language programs instead of shell script, which would be an advantage.

  • It seems you always find something just after you give up looking.
    – Iiridayn
    Jun 15 at 20:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.