Here’s a handy tip when you want to rename a file with a long path/name and don’t want to retype it twice.
I use Hugo for this blog and each new post starts with this command:
hugo new post/post-name which then generates a file at
But I like using Markdown, so that command should really be
hugo new post/post-name.md. When I inevitably forget and recognize this after running the command, I then need to rename this file to include the
# broken onto two lines just to make it more readable mv content/post/2020-09/some-long-article-name-with-lots-of-seo-goodness \ content/post/2020-09/some-long-article-name-with-lots-of-seo-goodness.md
It’s a little tedious to retype that long path/file. Here are two suggested approaches:
The first technique is called brace expansion. It lets you generate multiple strings by putting a comma separated list of values within braces.
In my example, if I want to rename the file to include the
.md extension, I can do this:
You can have multiple brace patterns within your string, and you can do more than just two values. I recommend checking the docs for more examples.
The second technique lets you auto-complete a value in the middle of your command.
After I’ve typed
mv content/post/2020-09/some-long-article-name-with-lots-of-seo-goodness, instead of re-typing the whole file path as a second argument, I can type
!#$ and then press
Tab and it auto-completes the first argument a second time. Now I can append
.md and hit
What is going on here? We’re combining two different concepts.
!# is called an
event designator and it let’s you refer to your command history. You could use this to refer to a command you typed 5 commands ago, but
!# refers to the currently command being typed right now.
$ is called a word designator. Just like events, you can refer to a variety of different word histories.
$ means “the last word”.
Putting those two things together,
!#$ means “the last word of the current command”, which in our case is that long file path we don’t want to retype. Pressing
Tab then performs the substitution.
There are a lot more uses for this type of behavior. Again, I recommend checking the docs. The history expansion topic covers this and more.
Note: even though I’m linking to the Bash docs, this works in
zshas well, which is my shell of choice.