
Renaming files with mv without typing the name two times - premek
https://gist.github.com/premek/6e70446cfc913d3c929d7cdbfe896fef
======
kelnos
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"):

    
    
        mv foo-bar-{baz,quux}.txt
    

You can have an 'empty' bit to add or remove something from the name (renames
"foo-bar.txt" to "foo-bar-baz.txt"):

    
    
        mv foo-bar{,-baz}.txt
    

That will work with pathname parts as well (as in the linked demo video) if
you include them in the command.

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.

~~~
naikrovek
I love/hate comments like yours.

You have technical knowledge applicable to the problem, and you share it. I
love that.

You miss an important feature of the solution shown in (I presume) your rush
to demonstrate your bash knowledge: the ability to edit a filename shown, in
place. Brace expansion doesn't do that, doesn't show you the new filename
_before you commit the name change_ and isn't even close to interactive. This
part is less great.

> Something like this isn't really necessary.

It may very well be necessary for someone else.

~~~
Godel_unicode
Not at all, you're just not thinking the solution all the way through. If you
want to see the results, an echo gets you there.

The important point though, is that one of the solutions moves you closer to a
common language with other posix users, and one moves you farther away. If you
use the tools the way they're intended to be used (brace expansion, for
example), you'll recognize it when other people use it. You'll understand
similar brace expansions in other commands you see others craft. You won't
need to remember if that shell you sudo'd into uses your override or not. The
reasons go on forever.

It really isn't necessary. That's not to say someone can't think of a reason
for it, but rather that there are better ways to do what it does.

~~~
titzer
For the OP's sake, I hope they completely ignore your advice.

Customize your environment to what makes you the most efficient. Yeah, sure.
Learn to use all the things that are there and understand what others do. But
_customize your environment to what makes you the most efficient_. This is an
interactive command. It's not like they are going to foist it onto everyone
else (which is the true sin, IMHO).

~~~
bb88
Changing the default behavior of a standard posix command is a footgun. It
would have been better to rename it.

~~~
Certhas
That's a valid constructive critique.

The people who are saying it's not necessary because they prefer alternative
ways of interacting with their machine are not arguing that though. The bit
the parent replied to was actually claiming that there is no valid reason to
do things this way (with a minor bash script) because there are other ways
(slightly mysterious curly braces hacks) that do something similar in some
cases... which is just, bizarre?

~~~
kd5bjo
'Godel_unicode > That's not to say someone can't think of a reason for it, but
rather that there are better ways to do what it does.

'Certhas > The bit the parent replied to was actually claiming that there is
no valid reason to do things this way … because there are other ways … that do
something similar

It appears to me that you're reading more into 'Godel_unicode's comment than
was written. Something not being necessary does not preclude it being useful,
and I haven't seen anyone imply otherwise except for you¹. Working through the
double-negative, 'Godel_unicode even explicitly acknowledges that some people
may have a reason to do things this way, despite their opinion that it's
inferior to their method.

¹ I haven't studied the entire thread, so it's likely I've missed someone's
comments.

~~~
Certhas
I read it as: You can think for a reason to do X but doing Y is strictly
better, so your reason is invalid.

I'm pretty sure what the comment doesn't say, also in tone, is something like:
Here are two options, X and Y, sometimes you might prefer one, sometimes the
other. Specifically look at the comment that Godel_unicode is disagreeing
with. That comment points out that some people might prefer the other solution
X for their own reason.

The way I read it, Godel_unicode replies that the person who is not using Y is
"not thinking things through", and is ignoring infinitely many reasons ("The
reasons go on forever.") to do Y. Even though you can come up with "a reason"
for X the infinitely many reasons for Y clearly beat it, and thus Y is just
objectively better.

Maybe the comment was intended more charitably than I read it.

~~~
kelnos
> _I read it as: You can think for a reason to do X but doing Y is strictly
> better, so your reason is invalid._

I think that's a much more strongly-negative interpretation than the text as
written calls for. My original post was nothing of the sort, and the reply I
think you're referring to was -- to me -- a nudge toward just simply realizing
that the standard tools that already exist are often much more powerful than
we think, and we can usually get 90+% of the way there without doing something
custom. And the 10% remaining isn't usually worth doing something non-standard
unless you have a very niche use.

------
kazinator
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:

    
    
       $ mv oldname _   # _ is your cursor
    

Now type Ctrl-W to erase the last word:

    
    
       $ mv _
    

Then type Ctrl-Y twice to yank it:

    
    
       $ mv oldname oldname _
    

Now edit in place as needed.

No utility needed, and just a regular mv command is issued whose inputs are
completely recorded in the history.

Now,let's automate that. Add this line to ~/.inputrc:

    
    
       # ~/.inputrc entry
       \C-T: " \C-W\C-Y\C-Y\b"
    

Reload with

    
    
       $ bind -f ~/.inputrc
    

Now Ctrl-T does it:

    
    
       $ mv oldname_
    

Hit Ctrl-T

    
    
       $ mv oldname oldname_
    

How about having Ctrl-T end up on the first character of the name?

    
    
       # ~/.inputrc entry
       \C-T: " \C-W\C-Y\C-Y\b\eb"

~~~
amelius
Doesn't work if the filename contains spaces:

    
    
        # mv "Foo bar" _

~~~
switch007
Ctrl-A, Alt-F, Ctrl-F, Ctrl-K, Ctrl-Y, Ctrl-Y

:D

~~~
kazinator
Ctrl-W Ctrl-W Ctrl-Y Ctrl-Y will work.

------
jacobsenscott
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.

~~~
bspammer
A good compromise to me seems to be using `imv` from the renameutils package
which is pretty much exactly the same as the OP. That way you don't get
confused by different `mv` behaviour on different systems.

Hitting `<Ctrl-a>i` seems to me a small price to pay :)

------
barrkel
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.

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.

~~~
sdegutis
Multiple cursors plus C-x C-q on a dired buffer is amazingly powerful: you
literally just make changes to the lines in the buffer and run C-c C-c to
commit them, or C-c C-k to cancel. I've used this for very powerful mass-
renames before. (I imagine it also works for deleting files by removing that
line but never needed to try it before.)

~~~
ashton314
I use Emacs inside iTerm2. (i.e. `emacs -nw`) Do you know if the multiple
cursors package (which I just found today thanks to your comment) works with
that? Or is it only in the native windowed version?

~~~
sdegutis
It works with terminal-based emacs too. It just inverses the background color
of cells to fake the extra cursors.

~~~
ashton314
That is a glorious hack. Thanks! I'll try it out for a spin!

------
JoshTriplett
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.

~~~
JadeNB
> 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.

This doesn't seem to work in readline's vi mode. Do you know the equivalent
there? EDIT: Ah, kesor points out elsewhere
([https://news.ycombinator.com/item?id=22861894](https://news.ycombinator.com/item?id=22861894))
that it's just 'v' in normal mode.

~~~
JoshTriplett
You can also bind "edit-and-execute-command" to another key in your ~/.inputrc
.

------
bb88
Graybeard here (never thought I'd say that). 25 years of unix/linux in
production systems.

Changing the default behavior of a posix command is a footgun.

If I wanted to get help from mv:

    
    
        $ mv --help
        Usage: file [OPTION...] [FILE...]
        Determine type of FILEs.
    

I get the help for the file command.

~~~
pwagland
And this is _exactly_ why, although this is cool, it would have been cooler
had it been renamed to, for example, `imv` (aka the name from the rename tools
project ;-) )

------
test1235
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.

~~~
class4behavior
Cunningham's Law

~~~
pwagland
This is the correct answer, however the question was obviously misstated. They
_should_ have stated that the answer was something else. :-)

~~~
test1235
I can't believe I missed that opportunity!!

------
lopsidedBrain
My trick has always been to rely on tab auto-completion.

    
    
        mv foo-<tab>
        mv foo-bar-baz foo-<tab>
        mv foo-bar-baz foo-bar-baz
    

Now I can edit the second part pretty quickly.

Downside: you have to at least type `foo-` twice.

Upside: command line history still has the full command.

~~~
loeg
Tab-completion is somewhat obnoxious in directories with lots of files sharing
a common prefix, for example.

Also, if you accidentally tab-complete the same file for output and input,
depending on how clever the program is, you may end up deleting the source
file.

~~~
saagarjha
I’ve done

    
    
      gcc foo.c -o foo.c
    

far too many times :(

~~~
loeg
Seems like gcc should be smart enough to reject that mistake nowadays, right?!

~~~
saagarjha
I should write a shell frontend to gcc to warn if I do this…

------
kemitchell
`qmv`, `imv`, `qcp`, `icp`, and friends from the `renameutils` package come in
handy. I use `qmv -f do ...` with `EDITOR=vim` quite a bit.

~~~
roryokane
Link:
[https://www.nongnu.org/renameutils/](https://www.nongnu.org/renameutils/)

On macOS with Homebrew, install with `brew install renameutils`.

------
Symbiote
Zsh users can instead add this to their .zshrc:

    
    
      autoload copy-earlier-word
      zle -N copy-earlier-word
      bindkey '^[,' copy-earlier-word
    

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>".

Also, given this:

    
    
      echo 1 2 3
      echo 4 5 6
      echo 7 8 9
    

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.

~~~
nerdponx
Alternatively you can use ZMV

[http://zsh.sourceforge.net/Doc/Release/User-
Contributions.ht...](http://zsh.sourceforge.net/Doc/Release/User-
Contributions.html#index-zmv)
[https://unix.stackexchange.com/a/19291/73256](https://unix.stackexchange.com/a/19291/73256)

------
l8again
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.

------
BiteCode_dev
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.

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:

    
    
        vidir filename
    

or

    
    
        vidir directory # default to .
    

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.

Note that if you use vscode, $EDITOR should be "code -w", not just "code".

------
baby
For things like this, I don’t understand why we don’t have more interactive
CLIs, instead of CLIs that expect one line of a bunch of arguments.

~~~
fl0wenol
Because it's the shell itself that gets the focus for the interactivity. You
use generic suggestions (as listed elsewhere in this thread) to do things like
tab-completion, substituting in previously used arguments, copying the last
thing you typed, etc. but they work across commands.

------
gitgud
If you rename the 'mv' command, won't this break a lot of things relying on
it?

~~~
downerending
Several distros unfortunately include 'mv' and 'cp' aliases by default. To get
predictable behavior on the command line, always use '\mv' and '\cp'. (for
bash)

~~~
JadeNB
I didn't know that! Why does it work?

~~~
downerending
The backslash basically means "ignore any aliases or functions by the same
name, and run the first matching command in my $PATH instead".

One reason for providing this is so that you can have an alias like

    
    
        alias mv '\mv -=myfavoritearg '
    

but it's also good for ensuring that you didn't pick up some distro nonsense.

~~~
JadeNB
Thanks! So '\' is special cased here—it's not some specific manifestation of a
more general phenomenon of specialised escape-handling in the shell?

~~~
a1369209993
> So '\' is special cased here

No; quoting any part of the command name prevents alias expansion. Eg 'mv',
"mv", 'm'v, m\v, etc all work.

------
reality101
type file then ctrl-a mv then ctrl-k ctrl-y space ctrl-y change file name
enter.

~~~
premek
nice, I didn't know about this

~~~
RMPR
Those keybindings belong to GNU readline
[https://en.m.wikipedia.org/wiki/GNU_Readline](https://en.m.wikipedia.org/wiki/GNU_Readline)

------
zwischenzug
I posted about some 'God-like' bash shortcuts here:

[https://zwischenzugs.com/2019/08/25/seven-god-like-bash-
hist...](https://zwischenzugs.com/2019/08/25/seven-god-like-bash-history-
shortcuts-you-will-actually-use/)

Number 6 was a 'refer to current line' one.

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.

------
Sierra-Sam
Here is my take on part of the problem.

    
    
        https://github.com/Guy-Shaw/libmmv
    
        https://github.com/Guy-Shaw/pmmv
    

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.

------
ara24
As has already been said, bash brace expansion is quite powerful. It has many
usecases, such as,

    
    
      diff file{.original,}
      mkdir -p path/{a,b,c}/folder
      for i in image{001..060}; do echo $i; done
    

Parameter Expansion is also equally useful, like changing a few characters in
long names,

    
    
      mv ${i}.png ${i/imaeg/image}.png

------
qsdf38100
Nice, feels like Windows File Explorer ;D

~~~
lucb1e
And nemo, caja, nautilus, finder, thunar, simple file manager, dolphin,
konqueror...?

There are more graphical environments than just Windows' built-in :|

------
idoubtit
I use zsh's function _copy-prev-shell-word_. You can bind it to some key, e.g.
alt-m with `bindkey "^[m" copy-prev-shell-word`. Use _ctrl-v shortcut_ for
another key.

For instance, adding a suffix to a file name: mv myfile _alt-m_.suffix

~~~
mkl
mv myfile{,.suffix} seems easier and more general, and doesn't need zsh.

------
lottin
You can accomplish the same with basic editing commands, e.g.

    
    
        mv <filename> C-M-b C-k C-y C-y
    

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.

~~~
outworlder
You can also do control+x control+e to send the command line to your
editor(whatever $EDITOR points to).

~~~
RMPR
On short commands, it tends to be slow in comparison of using GNU Readline
directly

------
dejj
Links for mass moving mentioned in the page:

\- 2018:
[https://github.com/lgommans/vinamer](https://github.com/lgommans/vinamer) \-
2017: [https://github.com/thameera/vimv](https://github.com/thameera/vimv) \-
2017:
[https://github.com/abaldwin88/roamer](https://github.com/abaldwin88/roamer)
\- 2006:
[https://joeyh.name/code/moreutils/](https://joeyh.name/code/moreutils/) ,
`vidir`

------
asamarin
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.

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:

    
    
      $ ls -1
      EL+�CTRICO_0001.jpg
      EL+�CTRICO_0002.jpg
      EL+�CTRICO_0003.jpg
      ...
    

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:

    
    
      $ perl-rename 's/\+\xeb/E/' *.jpg
    

Felt so good!

------
alexellisuk
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}`

This rarely saves me any time, but it's a nice hack to know about.

------
globular-toast
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).

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.

------
dnr
Here's my contribution to this useful class of scripts:

[http://dnr.im/tech/articles/mvdir/](http://dnr.im/tech/articles/mvdir/)

[https://bitbucket.org/davidn/mvdir/src/default/mvdir](https://bitbucket.org/davidn/mvdir/src/default/mvdir)

Similar to vidir, but predates it by a few years. I still use it regularly!

------
anthk
I just use vidir(1) an ed(1), I'm lazy :).

~~~
lucb1e
For those like me who don't know it, in Debian vidir is in the "moreutils"
package. As the name hints, its purpose is to "edit a directory in your text
editor".

------
reanimus
This is a nice alternative to using curly braces, especially when the changes
aren't simple substitutions :D

~~~
Twisell
Most people are bragging about braces while OP commented about that. It's
especially useful for multiple alterations.

------
yakshaving_jgt
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].

[0]: [https://github.com/thameera/vimv](https://github.com/thameera/vimv)

~~~
premek
I rename a single file much more often

------
lkuty
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.

------
rurban
Always surprising to hear of people not knowing the basic readline key
assignments.

Ctrl-w Ctrl-y Ctrl-y is still easiest for single files, rename for multiple.

------
inopinatus
For an interactive edit I just use <ESC>-. to repeat the last parameter:

    
    
        ls foo.txt
        mv <ESC>-. <ESC>-. # and edit

~~~
mrb
Yup, readline's yank-last-arg command Alt-. or Alt-_ (see
[https://www.gnu.org/software/bash/manual/html_node/Commands-...](https://www.gnu.org/software/bash/manual/html_node/Commands-
For-History.html#Commands-For-History)) is the best off-the-shelf solution
that still gives the ability to interactively edit the filename. To minimize
the total number of key strokes I would suggest:

    
    
      mv foo.txt 
      ↑
      Alt-.
    

That is: intentionally run mv with only one argument (the command fails but is
recorded in the history), Up arrow to recall the last command, and Alt-dot
(pastes the last argument).

This is literally replacing an entire shell script with two key strokes (Up,
Alt-.)

~~~
sigjuice
What version of bash do you use? I can't seem to get this to work with mine.
For me, Alt-. gets the last argument of the penultimate command.

    
    
      $ echo $BASH_VERSION
      5.0.11(1)-release
      
      $ mv foo.txt
      mv: missing destination file operand after 'foo.txt'
      Try 'mv --help' for more information.
    
      $ mv foo.txt $BASH_VERSION # Alt-. pasted $BASH_VERSION instead of foo.txt

------
bobowzki
"without typing the name two times"

Is that pun intentional? It's hilarious.

------
bmn__
`prename` is a thing; much more ergonomic than the solution in the article:

    
    
        $ prename '$_=lc; s/jpeg/jpg/' IMG0001.jpeg
        ### IMG0001.jpeg → img0001.jpg
    

This is probably the most reimplemented program I use, seven times last time I
counted.

~~~
shawnz
This doesn't seem more ergonomic to me, and also it is not the same solution
(OP also inserted a dash in the filename)

------
pvaldes
or... you can do this

mmv '<asterisk>foo<asterisk>' '#1bar#2'

where <asterisk> is the common symbol (Will not appear in HN)

------
matthewhartmans
I think this is really neat! Well done OP! :)

------
calvinmorrison
Shout out to visit(1) for lots of renames

------
xixixao
This post and the comments here show what a poor UI the command line is (by
default).

~~~
jpxw
It’s trivial to enable vim mode in most modern shells, which solves most of
these issues

~~~
kesor
And in `vi` mode it is as simple as hitting `v` to edit any command to your
liking before executing it.

------
sashavingardt2
Why is this at the top of HN?

~~~
wondringaloud
I've been asking myself that question more and more. It seems HN has been
slowly becoming a Reddit-lite. There are significantly more low-quality
"thanks! this is great!" comments and "witty" one-liners everywhere.

Not to mention posts like these.

~~~
dang
People have been saying this since before Startup News was renamed to Hacker
News in 2007:
[https://news.ycombinator.com/item?id=13852](https://news.ycombinator.com/item?id=13852)

[https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...](https://hn.algolia.com/?dateRange=all&page=0&prefix=true&query=turning%20%22into%20reddit%22&sort=byDate&type=comment)

More here:
[https://news.ycombinator.com/item?id=21755721](https://news.ycombinator.com/item?id=21755721)

