From help :help backtick-expansion
:
On Unix and a few other systems you can also use backticks for the file name
argument, for example:
:next `find . -name ver\\*.c -print`
:view `ls -t *.patch \| head -n1`
The backslashes before the star are required to prevent the shell from
expanding "ver*.c" prior to execution of the find program. The backslash
before the shell pipe symbol "|" prevents Vim from parsing it as command
termination.
If I type the command taken from the help, I get an error:
:next `find . -name ver\\*.c -print
E79: Cannot expand wildcards
Why does the example from the help use two backslashes instead of one, and why does it not work?
The following work:
If I remove one of the two backslashes which protect the star from being expanded by the shell before the
find
program::next `find . -name ver\*.c -print`
If I remove both of backslashes and put single quotes around the pattern
ver*.c
::next `find . -name 'ver*.c' -print`
Up to this point, the rule seems to be:
if your shell command contains a star and you don't want the shell to expand it before the command, put one backslash in front of it or put single quotes around the pattern.
But the help gives another example:
:view `ls -t *.patch \| head -n1`
This command works without any modification, no need of single quotes, no need of backslash.
I suppose the reason why it works is because the ls
command (contrary to the -name
argument of the find
command) accept multiple file arguments and sees no problem with the shell expanding *.patch
.
Now, let's say I want to look for all the files with the extension .conf
inside the /etc
folder and pipes the output of find
to grep
to get only the matches containing the string input
.
In the shell, from any working directory, I would type:
find /etc -name '*.conf' | grep input
And it would work.
In vim, I will type the same command putting backticks around it, and a backslash in front of the pipe symbol to prevent vim from interpreting it as a command termination :
:next `find /etc -name '*.conf' \| grep input`
And it works.
Now, if I type the same command without the pipe and the grep input
, I get an error:
:next `find /etc -name '*.conf'`
E79: Cannot expand wildcards
Why is there an error in this case even though I protected the star with single quotes?
And why is there an error now, but not just before with the pipe and the grep input
?
To try understanding, I've come up with a simpler command:
find . -name '*.conf'
It looks for all the files with the extension .conf
in the working directory. The command works in the shell.
To test it in vim, I typed: :next `find . -name '*.conf'`
And it works.
In this case the dot stands for my current working directory as displayed by the Ex command :pwd
which is my home directory /home/username
since I launched the vim session from it.
Why does it work when I ask to search in the current working directory whereas it doesn't work when I ask to search in an arbitrary folder such as /etc
?
Now, if I change my working directory from /home/username
to /etc
with the vim Ex command :cd /etc
and retry the same command as before, again it errors out:
:next `find . -name '*.conf'`
E79: Cannot expand wildcards
Why does the same command work when I'm in my home folder but not when I'm in /etc
?
I'm sure there's some logic, but I can't find one.
What is the general and correct syntax to populate the arglist with an arbitrary shell command (containing a star, a pipe, searching in any directory from any working directory) ?
I'm using vim version 7.4.942 and zsh is my default shell.
I tested these commands with a minimum of initializations (vim -u NORC -N
) from bash as well as from zsh.
Do I need to configure vim to call bash and not zsh ?
vim $(find . -name ver*.c)
vim $(find . -name ver\*.c -print)
,vim $(ls -t *.patch | head -n1)
,vim $(find /etc -name '*.conf' | grep input)
,vim $(find /etc -name '*.conf')
,vim $(find . -name '*.conf')
--remote
, see: vi.stackexchange.com/a/5618/4939) but I'm curious to know how to do it directly from the current session. If it's not possible that's fine, but after reading the help it seems it can be done. If it is, I would like to understand why vim reacts so differently to similar commands.find /etc -name '*.conf'
not working, I’d think some funny names come out of that command, and, this may be the reason why it worked when piped throughgrep
.