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.
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.
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.
$ echo mv foo{x,y}bar
> the ability to edit a filename shown, in placeEasily done right in the command line. First, type this:
$ mv oldname _
The _ denotes the cursor.Now erase the last word using Ctrl-W:
$ mv _
Now pastte it twie with Ctrl-Y Ctrl-Y: $ mv oldname oldname _
Edit in place, submit. mv foo.txt
↑
Alt-.
This works in bash and any shell using readline. Explanation: https://news.ycombinator.com/item?id=22863402OK, then just use !#$ (the last word of the current command) and press CTRL + ALT + e to expand it into the actual value.
Heaven forbid someone share knowledge. Let's interpret as uncharitably as possible and passive-aggressively love/hate.
> Brace expansion doesn't do that, doesn't show you the new filename before you commit the name change
Allow me to rush to demonstrate my zsh knowledge for any passersby who might benefit:
% mv foo-bar-{bar,baz}.txt|[TAB]
% mv foo-bar-bar.txt foo-bar-baz.txt
It's unfortunate that you reach for the uncharitable explanation first. To return the favor, I assume you rushed to post your reply because you think being contrarian and chastising the top-rated comment will get you more karma points? See, that wouldn't be cool... of course I don't actually believe that. While I don't agree with you, I assume you're arguing in good faith!
The simple fact is that I just don't see the need for it; after many years of heavy command-line use, I wouldn't use a tool like this. Either the simple case is sufficient, or I need something much more advanced, like prefix/suffix/regex replacement across multiple files (in which case shell variable expansion will often work, or I'll reach for `sed`). Beyond that, I try to avoid getting used to tools that only exist on my machine, and not on the tens of machines I ssh to weekly. (I already sometimes find myself, for example, attempting to use ripgrep on remote hosts that don't have it, and it's annoying.)
If you look downthread a bit, there are several comments that expand on doing it the "built-in" way that covers the original use case even more. For example:
Type "mv foo.txt" -> hit ctrl+w (cut word) -> hit ctrl+y (paste word) twice -> use arrow keys to edit.
Someone else mentioned fish will expand braces if you hit the <tab> key.
There are so many cool built-in things that the shell can already do for you; writing up a hacky solution that only works for one use case (the methods mentioned above work for mv, cp, ls, etc.) is limiting your learning and wasting your time.
> It may very well be necessary for someone else.
I really wish people would understand that when people make statements like I did, there's an implicit "for me" or "in my experience" tacked onto the end of that. Yes, obviously, people have different needs, and yes, obviously, I am talking about my own personal experience and needs. But I really do think that shell brace expansion covers the 90% case, and I was under the -- perhaps mistaken -- impression that the OP may not have known about it, or realize how it can be useful in this particular context. I knew about this sort of shell expansion for many years before I saw someone using it to do a file rename, and it was a big "wow, how have I never thought of that?" moment for me at the time; I expect that sort of thing happens to a lot of people.
In the cases where you need to do interactive edits of file names, something like emacs or mc is probably less error prone than bash.
Renaming via bash expansion has the additional advantage that it's script-friendly.
The real question is: why move files at all?
mv file.name{,.bak}
cp process.log{,.old}
etc. mv file.name !#:1.bak
cp process.log !#:1.old
!#:1 expands to the word with index 1. mv file file.bak; mv file.new file
Nested {} can handle that one, cutting four 'file's down to one: eval mv file{,{.bak\;mv\ ,.new},}
Anyone have a way to hack that to cut the two 'mv's down to one? foo-bar-{baz,quux}.txt = foo-bar-baz.txt
foo-bar-quux.txt $ echo {A,B}
A B
$ echo {A,B}{C,D}
AC AD BC BD
$ echo {A,B}{C,D}{E,F}
ACE ACF ADE ADF BCE BCF BDE BDF mv foo-bar-{baz,quux}.txt
becomes mv foo-bar-baz.txt foo-bar-quux.txtUnlike *, ? [a-z] ...
tar czf verylongdirectoryname{.tar.gz,}
Feel feel to replace czf with cjf for bz2, or cJf for xz. rename -n 's/baz/quux/' foo-bar-*https://www.gnu.org/software/bash/manual/html_node/Brace-Exp...
Importantly, realize it's a feature of Bash that deals with strings, not a feature of mv that deals with filenames. It just replaces a word containing a brace expression with a set of words that contain each pattern in the list.
In general, though, I wish that terminals and text editors that do nice things like syntax highlighting and autocomplete supported help text better. Perhaps selecting some text and hovering with your mouse or hitting F1 could bring up a minimal syntax example of the feature you're looking at...
mkdir /var/{log,spool,asdf,bar}
For others not aware of this functionality, it is a well documented and old bash feature:
https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.ht...
If you want to go deeper into the weeds, the parameter substitution bits are also very useful:
https://www.tldp.org/LDP/abs/html/parameter-substitution.htm...
mv foo-bar{,-baz}.txt(also "namsral" in the GitHub gist comment section beat you to the punch)
This syntax is no more obscure than a link in markdown, for example.
If you don't use it frequently, your are likely to forget it and it's not worth optimizing.
$ 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"GNU Readline's key bindings for Ctrl-W and Ctrl-U mimic these actions for consistency.
Ctrl-U is very useful for retyping a botched password at the login: prompt.
More importantly, if fixes the ctrl-w behaviour. By default c-w will delete up to the previous space. With set -o vi however, it deletes the same amount that vi considers a word to be. So if you're doing cd /a/long/dir and want to change it to /a/long/other/dir, pressing ctrl-w will only delete the last 'dir' instead of deleting the entire path. The default behaviour is highly aggravating.
# mv "Foo bar" _If you like spaces in filenames, you should use a GUI, anyway.
I recommend Windows Explorer; it's widely available.
The answer is a combination of:
* somebody submitted it
* people upvoted it
* the algorithm weights new more than old
* lots of people have things to say about it, including recommendations for other tools, neat hacks, and observations on general utility
Not to mention posts like these.
https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...
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.
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.
i don't alias mv to mv -i either, to avoid getting used to the idea that just mv is going to ask me, because i might work on a server where the alias is not set.
mv foo-bar <alt>-m
It’ll repeat foo-bar. It’s very useful. I miss it when I’m using Fish or Bash.
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) that it's just 'v' in normal mode.
- it only uses standard tools and keymaps, which pleases the bash greybeards.
- it uses your favorite-editor expertise instead of relying on situation-specific new/rare commands (Ctrl-W Ctrl-something what was it again?), which pleases the limited-braincache crowd.
- like the OP solution, it is interactive. you start typing mv something/yourfile, then realize things are going to get complicated: no need to backtrack, look up the manual for brace expansion, etc, just Ctrl-x Ctrl-e, do your thing. this pleases the intuitive UX crowd.
It's like going into a restaurant and ordering, without needing a menu.
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.
Actually I generally feel like I have superpowers when I use Emacs. The feeling was stronger than usual that day.
I've always used /bin/mv or /bin/ls to get just the command, but your method is shorter. (although I can't help but think of windows paths)
ls foo.txt
mv <ESC>-. <ESC>-. # and edit 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-.)
$ 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.txtChanging 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.Hitting `<Ctrl-a>i` seems to me a small price to pay :)
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.On macOS with Homebrew, install with `brew install renameutils`.
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.http://zsh.sourceforge.net/Doc/Release/User-Contributions.ht... https://unix.stackexchange.com/a/19291/73256
For instance, adding a suffix to a file name: mv myfile alt-m.suffix
$ 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.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".
https://zwischenzugs.com/2019/08/25/seven-god-like-bash-hist...
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.
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. 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- 2018: https://github.com/lgommans/vinamer - 2017: https://github.com/thameera/vimv - 2017: https://github.com/abaldwin88/roamer - 2006: https://joeyh.name/code/moreutils/ , `vidir`
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!This rarely saves me any time, but it's a nice hack to know about.
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.
http://dnr.im/tech/articles/mvdir/
https://bitbucket.org/davidn/mvdir/src/default/mvdir
Similar to vidir, but predates it by a few years. I still use it regularly!
Ctrl-w Ctrl-y Ctrl-y is still easiest for single files, rename for multiple.
Is that pun intentional? It's hilarious.
mmv '<asterisk>foo<asterisk>' '#1bar#2'
where <asterisk> is the common symbol (Will not appear in HN)