5

I want to be able to easily change the filename. This works:

:! var=%; mv % ${var/.txt/.asc}

But this doesn't:

:! mv % ${%/.txt/.asc}

My questions:

  • Why doesn't this work? Doesn't VIM simply replace % with the current filepath?
  • How can I use shell variable substitution with the current filename (in a more elegant way than the first I proposed).
9

Why doesn't this work?

This doesn't work for exactly why you say, vim is replacing the % with the path.

So, your non working line

:! mv % ${%/.txt/.asc}

is expanding to

:! mv myfile.txt ${myfile.txt/.txt/.asc}

which bash will call a bad substitution; You are trying to expand a variable called myfile.txt, and bash doesn't support variable names with . in them (and the . may mean something else).

How can I do shell substitution?

After a quick search, I could find no way to do substitutions without first assigning a value to a shell variable and operating on the variable itself.

Not what you asked, but you could achieve similar results using Vim's filename-modifiers (:help filename-modifiers) like so:

:! mv % %:r.asc

The :r after the % removes the last extension, and then we append .asc to it. The downside is that, if the extension wasn't .txt, we're still replacing it with .asc, but maybe that's what you want anyway.

Another example:

:! mv % %:s?.txt?.asc?

Which does exactly like your bash example, I think, and has the bonus of giving you the full power of Vim's substitute command on the filename. Here the :s modifier invokes substitute logic just like the :s ex command. Their example uses ? as the separation character instead of / because you are more likely to use / in file paths than ?.

The only thing you don't get are flags after the substituted text bit. Since the most likely flag you'd want is g (to match all occurrences on this "line"), you can use :gs?pat?sub? instead of :s?pat?sub?

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.