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?