Something like this isn't really necessary. I do something like this (bash) all the time when I want to change a part of a filename (renames "foo-bar-baz.txt" to "foo-bar-quux.txt"):<p><pre><code> mv foo-bar-{baz,quux}.txt
</code></pre>
You can have an 'empty' bit to add or remove something from the name (renames "foo-bar.txt" to "foo-bar-baz.txt"):<p><pre><code> mv foo-bar{,-baz}.txt
</code></pre>
That will work with pathname parts as well (as in the linked demo video) if you include them in the command.<p>I guess the linked script is useful if you need to do some complex edits to the filename, since you can't usefully have more than one curly-brace-group for this use case. But in that case honestly I'm fine just double-clicking the first argument to select, and then middle-clicking to paste, and then using the arrow keys to edit.
To make two copies of the last argument, so you can edit one of them in place, in Bash (or anything that uses GNU Readlne), simply do this:<p><pre><code> $ mv oldname _ # _ is your cursor
</code></pre>
Now type Ctrl-W to erase the last word:<p><pre><code> $ mv _
</code></pre>
Then type Ctrl-Y twice to yank it:<p><pre><code> $ mv oldname oldname _
</code></pre>
Now edit in place as needed.<p>No utility needed, and just a regular mv command is issued whose inputs are completely recorded in the history.<p>Now,let's automate that. Add this line to ~/.inputrc:<p><pre><code> # ~/.inputrc entry
\C-T: " \C-W\C-Y\C-Y\b"
</code></pre>
Reload with<p><pre><code> $ bind -f ~/.inputrc
</code></pre>
Now Ctrl-T does it:<p><pre><code> $ mv oldname_
</code></pre>
Hit Ctrl-T<p><pre><code> $ mv oldname oldname_
</code></pre>
How about having Ctrl-T end up on the first character of the name?<p><pre><code> # ~/.inputrc entry
\C-T: " \C-W\C-Y\C-Y\b\eb"</code></pre>
All the "something like this isn't really necessary, just memorize all the esoteric bash globbing rules" posts are so far off, given the solutions in all those posts aren't really necessary either. It is nice not to need to "pre-think" how you are going to type your `mv` command. You just start typing it, and when you realize it will be a bit complex you just hit enter and you have an editor.
Any time renaming gets more complicated than (a) bash curly braces or (b) rename command (Perl script that applies sed expression to each file name), I break out Emacs wdired.<p>Then you can use all the Emacs tools to perform a mass edit across multiple file names, and get them right before committing to the rename. Multiple cursors makes a great addition, as does iedit-mode.
You can also hit Ctrl-x Ctrl-e to edit the command line in your preferred text editor, and run it when saved and closed in the editor. So you can type the mv, tab-complete the current filename, and use the editor for the new filename.
Graybeard here (never thought I'd say that). 25 years of unix/linux in production systems.<p>Changing the default behavior of a posix command is a footgun.<p>If I wanted to get help from mv:<p><pre><code> $ mv --help
Usage: file [OPTION...] [FILE...]
Determine type of FILEs.
</code></pre>
I get the help for the file command.
I can't remember where it was I read (saw this years ago), but the way to actually get help online isn't to ask a question 'cos nobody responds ... you have to propose an incorrect solution where suddenly everyone jumps up to correct you with the answer you're looking for.
My trick has always been to rely on tab auto-completion.<p><pre><code> mv foo-<tab>
mv foo-bar-baz foo-<tab>
mv foo-bar-baz foo-bar-baz
</code></pre>
Now I can edit the second part pretty quickly.<p>Downside: you have to at least type `foo-` twice.<p>Upside: command line history still has the full command.
Zsh users can instead add this to their .zshrc:<p><pre><code> autoload copy-earlier-word
zle -N copy-earlier-word
bindkey '^[,' copy-earlier-word
</code></pre>
Then it's the default Alt-dot to copy the final argument of the previous command, and Alt-comma to copy the final argument of the current command. The move command is then "mv filename <Alt-Comma>".<p>Also, given this:<p><pre><code> echo 1 2 3
echo 4 5 6
echo 7 8 9
</code></pre>
Then on the next command, Alt-dot will copy/replace 9→6→3. Pressing Alt-comma after Alt-dot will replace that with 8→7→echo.
This is one of those times when I just love coming to hacker news. Seemingly trivial quality of life improvement makes it to the top and the comments section is lit up with several other cool alternatives.
I think it's very nice, and should be the default behavior. Ergonomics of GNU tooling is lacking to say the least. That's why we love fdfind and ripgrep and love find/grep way less.<p>I would use it if it were the default behavior, but the problem is already solved by the "moreutils" package, which I install on all my machines. This lets you do:<p><pre><code> vidir filename
</code></pre>
or<p><pre><code> vidir directory # default to .
</code></pre>
And it will open your $EDITOR with one file name per line. You edit it in the comfort of your favorite editor, and it batch renames for you, or rename the single file for the first case.<p>Note that if you use vscode, $EDITOR should be "code -w", not just "code".
I posted about some 'God-like' bash shortcuts here:<p><a href="https://zwischenzugs.com/2019/08/25/seven-god-like-bash-history-shortcuts-you-will-actually-use/" rel="nofollow">https://zwischenzugs.com/2019/08/25/seven-god-like-bash-hist...</a><p>Number 6 was a 'refer to current line' one.<p>There are so many ways to do these things that it's hard to get them all under your fingers though. Most of the time I tab my way through the 'problem' anyway.
Here is my take on part of the problem.<p><pre><code> https://github.com/Guy-Shaw/libmmv
https://github.com/Guy-Shaw/pmmv
</code></pre>
The original perl-rename has the expressive power, but not the safety features. mmv has been around since 1990 and, in my opinion, has always been under-appreciated, but it could use some modernization.
As has already been said, bash brace expansion is quite powerful. It has many usecases, such as,<p><pre><code> diff file{.original,}
mkdir -p path/{a,b,c}/folder
for i in image{001..060}; do echo $i; done
</code></pre>
Parameter Expansion is also equally useful, like changing a few characters in long names,<p><pre><code> mv ${i}.png ${i/imaeg/image}.png</code></pre>
I use zsh's function <i>copy-prev-shell-word</i>. You can bind it to some key, e.g. alt-m with `bindkey "^[m" copy-prev-shell-word`. Use <i>ctrl-v shortcut</i> for another key.<p>For instance, adding a suffix to a file name: mv myfile <i>alt-m</i>.suffix
You can accomplish the same with basic editing commands, e.g.<p><pre><code> mv <filename> C-M-b C-k C-y C-y
</code></pre>
It may seem overly complicated but notice that you don't have to release the control key, so it's actually very few key strokes.
The latest addition to my renaming-toolbelt has been `perl-rename'. This thing is just wonderful: I can unleash all the power of perl-based regexes to rename things in bulk.<p>Case in point: I had a directory containing thousands of .jpg images imported from a foreign filesystem, and all of those files had tildes in them, something like:<p><pre><code> $ ls -1
EL+�CTRICO_0001.jpg
EL+�CTRICO_0002.jpg
EL+�CTRICO_0003.jpg
...
</code></pre>
You get the idea; note those ugly unrepresentable characters over there. On the original filesystem they read as "ELÉCTRICO", but that tilde was saved using who knows what encoding, and I simply wanted to get rid of them and have nice ascii "ELECTRICO_xxxx.jpg" files. After finding out that the strange unrepresentable character was the byte 0xEB (so, in order to form an "É" you needed those two characters together: a literal '+' and 0xEB), I could do the bulk renaming with just:<p><pre><code> $ perl-rename 's/\+\xeb/E/' *.jpg
</code></pre>
Felt so good!
For faas-cli-darwin -> faas-cli, I just do `mv faas-cli{-darwin,}` or `faas-cli.tgz` -> `faas-cli.tar.gz` -> `mv faas-cli faas-cli.{tgz,tar.gz}`<p>This rarely saves me any time, but it's a nice hack to know about.
I discovered the `rename` command surprisingly late in my career. You could write something like this: `rename .htm .html index.htm`. The nice thing is it works for any number of files at once (you could put a glob on the right, for example).<p>Oddly I just checked my Ubuntu machine and it had the man page for rename but not the command. After being prompted to install it it installed a completely different perl command and upon removing that the original manpage was gone. Very strange.
Here's my contribution to this useful class of scripts:<p><a href="http://dnr.im/tech/articles/mvdir/" rel="nofollow">http://dnr.im/tech/articles/mvdir/</a><p><a href="https://bitbucket.org/davidn/mvdir/src/default/mvdir" rel="nofollow">https://bitbucket.org/davidn/mvdir/src/default/mvdir</a><p>Similar to vidir, but predates it by a few years. I still use it regularly!
Renaming a single file is not very interesting. Renaming a whole bunch of files is much more interesting, and when I need to do that, I use vimv[0].<p>[0]: <a href="https://github.com/thameera/vimv" rel="nofollow">https://github.com/thameera/vimv</a>
That's why I love HN comments. Always learning a lot of stuff and regularly the comments are more interesting than the original post itself. This is the case for this one I think. Or at least a nice complement.
For an interactive edit I just use <ESC>-. to repeat the last parameter:<p><pre><code> ls foo.txt
mv <ESC>-. <ESC>-. # and edit</code></pre>
Always surprising to hear of people not knowing the basic readline key assignments.<p>Ctrl-w Ctrl-y Ctrl-y is still easiest for single files, rename for multiple.
`prename` is a thing; much more ergonomic than the solution in the article:<p><pre><code> $ prename '$_=lc; s/jpeg/jpg/' IMG0001.jpeg
### IMG0001.jpeg → img0001.jpg
</code></pre>
This is probably the most reimplemented program I use, seven times last time I counted.
or... you can do this<p>mmv '<asterisk>foo<asterisk>' '#1bar#2'<p>where <asterisk> is the common symbol (Will not appear in HN)