I'm trying to write a vim function to update ctags and cscope databases. I'm trying to save the vim variable projectRoot in environment variable then expand this enviroment variable in the find command. But it is not working. Here is my try:

let projectRoot="/mnt/hgfs/projects/myProject/"

function! UpdateTagDB()
   :cd /
   :execute("let ProRoot=".g:projectRoot)
   :find $ProRoot -name '*.c' -o -name '*.h' > $ProRoot/cscope.files<cr>
   :execute("cd ".g:projectRoot)
   :!ctags -R .<cr>
   :!cscope -bR<cr>

nnoremap <F5> :call UpdateTagDB()

When hitting F5, it gives me:

line 2:
E15: Invalid expression: /mnt/hgfs/projects/myProject/
line 3:
E345: Can't find file "$ProRoot -name '*.c' -o -name '*.h' > $ProRoot/cscope.files<cr>" in path

What is missing and how to get it to work?

1 Answer 1


The :execute command will assemble an Ex command from strings and evaluate it.

Here, in this case, it's actually breaking your command, since it's expanding the g:projectRoot string and forming a string that is an invalid Ex command, since the quotes around the path are now missing. That command is actually equivalent to:

let ProRoot=/mnt/hgfs/projects/myProject/

Just drop the :execute should be enough to fix it.

Also, to set an environment variable, you need to use the $ prefix on the let command as well.

let $ProRoot = g:projectRoot

Finally, you don't need : anywhere inside a Vimscript function, it's all executed as Ex commands anyways. (The : doesn't break it, but it looks much nicer without it.)

Finally, your find is a shell command, so you need a ! to have it executed by the shell.

There are a few more issues in the following lines, namely you shouldn't have <CR> at the end of commands, and you shouldn't have parents on the :execute for cd (parents denotes a function call, but this should be a command.)

Putting it all together:

function! UpdateTagDB()
    cd /
    let $ProRoot = g:projectRoot
    !find $ProRoot -name '*.c' -o -name '*.h' > $ProRoot/cscope.files
    execute "cd ".g:projectRoot
    !ctags -R .
    !cscope -bR

Finally, you do need a <CR> in your :map command. You probably also want to make it <silent> so it doesn't print the :call command on the command-line when executed:

nnoremap <silent> <F5> :call UpdateTagDB()<CR>
  • 1
    Many thanks for clarifying all these points. Nov 18, 2020 at 13:55
  • 1
    One more point. When runnging the function, it displays three times Press ENTER or type command to continue in the command line. I have to hit ENTER three times to allow it to continue. Is there a way to get it to continue without hitting ENTER? Nov 18, 2020 at 13:59
  • 1
    Yes, use :silent to suppress these. See :help :silent (and also :help :!). Remember you don't need the : here, so silent !find ... should be enough. Sometimes you might need :silent! with an extra !, but I think that's not really the case here, plain :silent should be enough.
    – filbranden
    Nov 18, 2020 at 14:03
  • 1
    It worked. Thank you Nov 18, 2020 at 14:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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