Hacker News new | past | comments | ask | show | jobs | submit login
Renaming files with mv without typing the name two times (gist.github.com)
669 points by premek on April 13, 2020 | hide | past | favorite | 267 comments



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.


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.


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.


Personally, I just use a tiny magnet to flip bits on a metal disk. If you want to see the results, you can use an AFM.

You see, a shell really isn't necessary to interact with a computer. The big advantage is that, as you are working on the physical laws they will be the same at any computer you will use! It's the only solution that is universal. No need to remember whether the machine you're working on has Windows or Linux installed!

Sure you can come up with "reasons" to do things differently, but, not by argument, but by fiat, I tell you that they are irrelevant and my way is strictly the better way to do things.


Who uses that when you have butterflies?

But if one needs to see the name before committing a change, there is https://superuser.com/questions/215950/how-to-expand-on-bash...


That's useful, thanks!


Sigh. Nearly every Linux/macOS/UNIX box you run into will have bash or something that will do brace expansion. Same goes for having standard tools like sed, awk, echo, etc.

You can't say the same thing about a bespoke shell function that gives you editable renames.

> Sure you can come up with "reasons" to do things differently, but, not by argument, but by fiat, I tell you that they are irrelevant and my way is strictly the better way to do things.

That's not what anyone is doing and you're attacking a straw man.


I'm all for standardizing tools but when it comes to interactive commands I don't really see the problem to customize for your particular use case. The only drawback is that it makes it a bit more frustrating to use a 3rd party computer but I spend 90% of my time on my own computers where I can easily import my config files.

In this particular instance I also don't find braces much more ergonomic at all. I typically navigate the filesystem using tab completion, that means that I'm going to end up with a full path like:

    mv /foo/bar/some_complicated_file_name.txt |
And then at this point I have to backtrack to add the braces at the right location. In this situation I find TFA's solution more straightforward and more elegant.

I think a more productive advice would be "don't customize something until you've given existing solution a fair chance". It's easy to go overboard with customization and make it counter productive. It's important to understand the mindset of the people who wrote the tools and whether you're truly facing a limitation or the system or if you're "doing it wrong".

For instance I personally love zsh's global aliases and have "G" aliased to "| grep" for instance. So I can write for instance "some_command G something" to grep through the output. I also have "M" bound to "| less". Probably saved me tens of thousands of keystrokes through the years.


no love for the "rename" commmand 'rename foo bar *'


It even handles regex (and capture groups!)! I think the issue here though is that it's not always available by default depending on repo.


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


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


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?


> The bit the parent replied to was actually claiming that there is no valid reason to do things this way

That is not actually what anyone in this thread has claimed.


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


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.


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


> It would have been better to rename it.

Maybe. It's worthwhile pointing out that "mv x" with no second argument is an error:

  mv: missing destination file operand after 'x'
  Try 'mv --help' for more information.
I also don't have the habit of letting people type in my shell, so there's that.

TBH I really don't understand the level of pedantry (and frankly, sheer outrage) in this thread at all. It sucks to be on the receiving end of such disapproval over something so trivial. Let this person do what they want! It's a neat little hack. It also inspired me to see what more I could do with 'read'--something I have ignored for 20 years.


    $ mv --help
    Usage: file [OPTION...] [FILE...]
    Determine type of FILEs.
So mv --help now returns the help for the `file` command. You're right, that's not worth warning people at all.

God help any user that's on a shared system whose sysadmin thinks this is a good idea putting in the default /etc/profile.

To be fair, I don't feel like I'm being pedantic. I'm anti-footgun.


> sysadmin thinks this is a good idea putting in the default /etc/profile

Well that, I agree, would be dumb.


You could just filter out anything that begins with a dash and pass it to mv. It seems like mv always interprets that as an option anyway, even if you have a file named --help or whatever.

I like this kind of thing! Minimal code but very elegant from a UX perspective. The oh but you could just mv foo-{bar,baz}.txt crowd is completely missing the point.


> The oh but you could just mv foo-{bar,baz}.txt crowd is completely missing the point.

I disagree. I think a better way to think about things is, "can I accomplish my goal most of the time using the standard tools without writing something custom?" I'll be the first to admit that there are a ton of things in the shell and in coreutils that I don't know about. I bet I've written several scripts over the years with custom functionality that could be replaced with standard tools I didn't know about. That's the thing that I want to avoid.


I love bash. I love unix/linux. I love that bash gives you that kind of power. I love the fact that he figured out a nifty way of doing this.

But please please please please with all the love of America, baseball, and apple pie, don't change the default behavior of basic unix commands.

Otherwise you force people into writing nonsense like this:

MV=/usr/bin/mv

${MV} ${FILE1} ${FILE2}


> (and frankly, sheer outrage)

I think you're reading way too much into what I and others are saying. Honestly I'm finding being misunderstood and mis-characterized as angry to be the only thing that's bothering me.


> Customize your environment to what makes you the most efficient.

This is a valid advice, but on a fundamental level, how is it better or worse than "Learn to be the most efficient for your environment" ?

IMO it comes down to which is harder/expensive, changing yourself or your environment, and on this site in particular, I don't think there is a clear consensus on one or another.


> changing yourself or your environment

After more than 25 years of using software, IMHO it's a losing battle to try to change the environment around you. It's also a losing battle to try to change yourself. You'll never keep up in the long run. After a while the pace of change becomes so rapid, and change comes from every corner at every level. Eventually what you once knew becomes useless and outdated. You can keep up to some extent, but be prepared for a lifetime of unpleasant surprises.

What works, IMO, is instead to build an environment around yourself that works for you, that protects you from the things changing that you can't control. An internal abstraction layer, a bubble. Then when the bubble breaks in little pinpricks and starts crumbling, you can repair the internal environment to be pretty much what it was before. So by all means, make your own little commands and scripts and stuff. Get cozy, but try to pick your battles wisely on what you will depend.


Hat's off on your 25 years!

Some of us are doing crazy stack switches mid-carrier, so maintaining a bubble around us can be a difficult option. I remember being day-in-day-out in Eclipse doing Java, and switching to a different stack meant throwing it all through the window and finding out what were the most optimized tools for the new set of tasks that will be done hundreds of time a day.

I see the same thing happening with people switching away from iOS dev for instance.

But I also agree we are in a privileged positions where on most tools we can build ourselves the layers to make it look/behave like familiar things. Especially for tools like bash or vim that purposefully change at a glacier pace compared to the rest of the stack.

I guess we usually take both approaches of learning new things to be more efficient and also building/customizing things as we see the parts where we don't want/can't change our behavior.

> Get cozy, but try to pick your battles wisely on what you will depend.

I like this phrasing a lot; nicely put.


That's feasible only in some scenarios. Nowadays you often need to interact with new environments and be instantly productive in them. Also, it makes little sense trying to receate the same cozy environment between, say, EC2, WSL and FreeBSD hosts when you need to interact with them for a very short time. Welcome to the era of disposable computing.


This only works when you are strictly working with one machine that is your own, instead of many machines, that are not your own. Customizing every machine I touch is more hassle than to just master the tools that are already in place.


There seems to a large contingent of linux users who are somehow completely immune to garbage user experience. It's really impressive.


I don't use bash for ideological reasons. I use it to get things done and I much rather prefer this script than having to use curly braces and echo.


Out of curiosity, what are you reasons for not using bash?


I think they mean that they do use bash, but the reason that they use it is not ideological. Tricky sentence to work out.


Oh, you're right. Honestly had I truly read the whole sentence I probably would have figured that out.


As I understood their comment, they do use bash but not for any ideological reason but rather to get things done.


> doesn't show you the new filename

  $ echo mv foo{x,y}bar
> the ability to edit a filename shown, in place

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


Using echo is the wrong way. What you do is ‘CTRL-x *’. That will expand any glob right there on the command line.


Brace expansion isn't a glob, unfortunately. Did you try it?


I didn't know the `CTRL-x * ` expansion; it appears to work in zsh for brace expansion:

  $ touch asdf-{gh,jk}-l
  # CTRL-x *
  $ touch asdf-gh-l asdf-jk-l


In zsh you can use tab to expand globs/braces/variables as well.


I didn't know about that.

I tried control-x escape, that only does variable expansion (and it appears to expand aliases too)


Or I just use this script which is much more intuitive and convenient.


In my other post, I got the readline method down to one control code. You type "mv name" and hit the assigned control character, which produces a second copy of the name that you can edit in place. It works with any command: mv, cp, ln, git mv ... The editing is in the same command line, resulting in a proper argument that is in the command line. It gets saved into your history, and can be pasted into a script.


But only solves one use case. Why not learn how to do it for every other unix tool?


I don't see how this script prevents me from learning it. With that said, we're obviously in different ballparks when it comes to the terminal. I don't need to do anything fancy. cd, ls, mv and git are pretty much the only commands I ever use. For me, this script fits nicely into my workflow.


But it's... not? What if I want to use the same trick with 'cp'? Do I go and copy-paste my script, or maybe spend time to make it generic enough to handle both commands? That's not a good use of my time when the shell will do it for me, if only I'd spend a minute to learn.


Agree with you. Said in another word, "Their statement is correct but misses the point"[1]

[1]: https://news.ycombinator.com/item?id=22854475


Interactively editing the filename is possible with this even simpler solution:

  mv foo.txt 
  ↑
  Alt-.
This works in bash and any shell using readline. Explanation: https://news.ycombinator.com/item?id=22863402


Great tip thanks!

Similarly, readline's vi mode makes interactive editing in place easy


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

OK, then just use !#$ (the last word of the current command) and press CTRL + ALT + e to expand it into the actual value.


Zsh can expand expansions before you execute a command


At least with the `fish` shell, you can use "Alt-E" to edit any command line. It's a visual, interactive, re-usable solution that shows the result before you commit it.


Is that different to bash or zsh?

Both support editing using either vi or emacs shortcuts via readline.


> (I presume) your rush to demonstrate your bash knowledge

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


In my `set -o vi` bash I can type `v` to edit the command in vim before executing it.


For the record, you can do this with C-x C-e without vi keybindings


The more I read these comments/suggestions, the more I realize I'm bash'ing like a child. I seriously need to embrace my shell a little more.


Same for me. I knew the bash has emacs bindings and I know just enough to go to beginning, end, delete a word, etc. but I never knew you can start emacs with a shortcut like this. How do you even exit emacs properly?


C-x C-s to save, C-x C-c to quit.

But you can also control which editor is going to be used to edit your command line by setting the EDITOR environment variable.

It also works for git, and other commands that need to spawn editors.


I never knew that existed.

My first thought was "emacs editing characters already work on the command line."

Then I thought, maybe there are commands you want to be really really sure of before submitting them?

Then I realized I very frequently use very long commands with loops and pipes that might benefit, like:

  for i in *.py; do mv $i AA_$i; done
or a little of both:

  find . -type f |while read f; do if cmp -s "$f" ../new/"$f"; then rm -f "$f"; fi ;done
(thanks!)


> in (I presume) your rush to demonstrate your bash knowledge

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.


Interactive editing is generally something to avoid. It can't be part of a bash script, or a puppet manifest, or checked into version control.

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.


If interactive editing is the big win, you can install 'mc' and it will give you many more interactive editing capabilities.

Renaming via bash expansion has the additional advantage that it's script-friendly.


I really like that zsh can be set to expand globs on tab, both useful for editing when a glob is “close enough” and for checking the result quickly. I think a lot of the value of a script like this is you don’t have to switch contexts or think any different before you use it.


Not just that, but the time it takes me to get the braces correct is usually more than it takes me to just select the damn thing with a mouse, paste it, and modify it...


Could use mv -iv for interactive and verbose if you want a rollback or commit alternative.

The real question is: why move files at all?


For the same reason you move stuff in your room. You don't always put it into right places. Or someone else has put it somewhere.


Also, typing braces are annoying. To think about it from a UX perspective, this solution on gist, judging by the video, is perfect.


Let me just say that typing {}[] is super painful on many international variants of QWERTY. Typically you need to press a modifier for both (Alt Gr).

https://en.wikipedia.org/wiki/QWERTY#International_variants


Which is why if you're a programmer, you're doing yourself a disservice by not using a keyboard with a US layout.


Full agreement from me. My ergonomics and efficiency both improved immensely when I switched from my native layout to US International.

With US International, unless I want to hit the key combo to change layouts, I can still write a single or just a few umlauts (say, for a person's name).

I find it easier to keep my focus when I don't have to make the right wrist twister that is otherwise required for { if using a Swedish layout.


Also try setting caps as compose key and using the standard ANSI layout. Solves the problem of always having to double press characters such as quotes.


Minor point: or the UK layout, for a European keyboard (ISO keyboard) with the tall enter key, rather than the American ANSI layout with a wide enter.

The extra key on the UK layout brings # without shift, which is useful, and £ and ¬ which presumably aren't, but could be remapped to something more useful like € and an accent.


As a UK user I switched to an alternative layout many years ago for RSI reasons. My preference is Colemak but I don't think it matters too much which layout you opt for.

For me the advantage, other than less finger travel, is that the markings on the keys don't match the layout I use. I've been forced a long time ago to commit it all to memory and learn to touch type without looking at the keyboard.

Touch typing is a small thing but is a massive productivity boon just on it's own even if you're not a speed daemon because you don't have to think to type.


Touch typing is not a small thing.


UK layout makes it hard to press enter or left shift. I find it frustrating and bad for my joints.


I'm only suggesting it for people already used to that physical layout of the keys. Germans, French, Spanish, Swedish etc.

It means they can continue to use normal keyboards (including on laptops) in their country.


I totally agree with this. Another problem are some programs where shortcuts seem to bind to some hardware codes of keys instead of what your layout says, so that shortcuts aren't what they say they are, e.g ctrl+[ would be at ctrl-å instead of ctrl+altGr+9 on a swedish keyboard (which I guess couldn't work because altGr is the same as ctrl+alt, or is that not true?)

In my situation I write in english, swedish, danish and sometimes icelandic as well as in programming languages. My solution has been to create my own keyboard layout that I call Nordic Programmer which is the US keyboard but by pressing altGr I have åäö letters where they are supposed to be, and øæ next to them. and then on altGr+eyuioadt i have éýúíóáðþ for icelandic. All of them are capitalized by adding shift. This was pretty easy to learn to use and makes me not have to switch keyboard all the time. It is not truly nordic I guess, because it prioritizes swedish which is the keyboard I learned growing up.


> shortcuts seem to bind to some hardware codes of keys instead of what your layout says

You don't say what platform you use, but this can be true of Windows and Windows-derived systems (which includes a lot of web stuff on all platforms because Netscape foolishly exposed Windows internal key codes 25 years ago). The non-alpha VK (virtual key) codes migrate all over the place¹ or worse disappear (e.g. Turkish doesn't have the VK corresponding to US +/= at all).

I used to work on Chrome OS which currently does this (trying very hard to emulate the Windows rearrangements due to the Netscape web legacy) but will shortly try the “what they say they are” method behind an experimental flag; that is, for example, the shortcut Ctrl+[ would be typed by Ctrl plus whatever you type to get ‘[’.

¹ http://kbdlayout.info/


Yes, it's on Windows I have experienced this issue.

I'm not familiar with the low level mechanics of this but you seem to be. How would it work to do what you write at the end? Isn't altGr just an easier way of typing ctrl+alt? Getting ctrl+[ would then be ctrl+ctrl+alt+9. Or is it a proper key of its own?


AltGraph is physically the key that is right-Alt on US keyboards. My understanding is that Windows has Ctrl+Alt as an alternative because some long ago PS/2 keyboards didn't distinguish the two Alt, so it wouldn't be able to take the same approach.


Couldn't agree more, was using the French layout and while learning vim I always asked myself what are those weird keybindings, switching to US layout, they suddenly started to make sense because the keys are more reachable without the usual gymnastic.


So true. In a month I will receive my new laptop with a qwerty US layout instead of the belgian azerty one I used until now. Using an external keyboard for now, I already see the benefit of qwerty for programmers. And I also switch from macOS to Linux with i3wm.


I never understood why most programming languages where so heavy in brackets until I moved to the UK and saw the layout. Then it clicked.


From a UX perspective use a gui file explorer, double click rename.


This is a technique I use often:

    mv file.name{,.bak}
    cp process.log{,.old}
etc.


An alternative is:

  mv file.name !#:1.bak
  cp process.log !#:1.old
!#:1 expands to the word with index 1.


And it supports regex replace as well

    $ echo foobar !#:1:s/foo/bar
    echo foobar barbar
    foobar barbar


slightly shorter !#$

and i always use ctrl-alt-e to expand and check even if i dont want to edit


I didn't know about the Ctrl-Alt-E so that's useful to know when using a new computer or a shared user account. I have `shopt -s histverify` set in my own bashrc. It's a useful sanity check when using history expansion. After typing the command, press Enter to see what it expands to, verify that it's what I intend and hit Enter a second time to confirm the comand.


Another common rename is the three way:

  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?


> Anyone have a way to hack that to cut the two 'mv's down to one?

Yup:

    mv -bS .bak file{.new,}
Should give the same result if you're using gnu coreutils 'mv', though it's obviously not as generally useful as nested braces.


I didn't know {} could nest!


It sorta can't... note the use of eval.


The eval isn't to help with the nesting. The {} stuff nests just fine, as we can see by changing the "eval mv" to printf:

  $ printf '[%s]' file{,{.bak\;mv,.new},}
  [file][file.bak;mv][file.new][file]
(Note: I took out the '\ ' from the original because I realized it is not necessary).

The eval is there because in bash text expansion occurs after ';' is interpreted, and we need that to be the other way around. Hence, the escaping of ';' in the input to preserve it for text expansion, and then the eval afterward to get ';' interpreted.


Sorry, I should have checked.

I jumped at it because there are other things one might like to achieve with brace expansion but turn out to be impossible because it is evaluated first - you can't use them with variables.


Why does this work? I always thought brackets were used to select a set of files. For example

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


Don't think of it as selecting files. It's just simple string substitution/expansion. "foo-bar-{baz,quux}.txt" just expands to "foo-bar-baz.txt" and "foo-bar-quux.txt", which are then passed to "mv" as separate arguments. The corresponding files need not exist, as this is a separate bit of functionality than file globbing.


Pathname expansion (i.e. globbing) can't even be used this way as POSIX requires matched names to be lexicographically sorted. That's the first thing that came to mind, before I remembered that brace expansion is a widely-supported extension not defined by POSIX.


Brace expansion doesn't fall under pathname expansion. There is no expectation that the resulting expansion will correspond to files. From `man bash`:

> Expansion is performed on the command line after it has been split into words. There are seven kinds of expansion performed: brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, word splitting, and pathname expansion.

That's not to say it's POSIX-compliant--I have no idea whether it is. But it definitely isn't grouped in with pathname expansion. bash does have an option to disable brace expansion, but it's not toggled by `--posix`, which leads me to believe it might be POSIX-compliant.


> Brace expansion doesn't fall under pathname expansion.

I thought that was implied in my post, but perhaps I should have made it explicit.

> That's not to say it's POSIX-compliant--I have no idea whether it is

I didn't know one way or another, but since you brought it up, it looks like it probably is not compliant. See, e.g., this argument that `echo {1,2}` must print '{1,2}' because POSIX doesn't require '{1,2}' to be quoted: https://www.austingroupbugs.net/view.php?id=1193

Brace expansion is a nearly universally supported extension, though, so I doubt it's a real problem. And the above link proposes fixing the standard to make the extension compliant.


Braces just evaluate and expand.

    $ 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


Wow, I had not realized that one could compute Cartesian products using a shell.


On the topic of things you didn't know the shell did: I found out about sequences recently and love them:

$ echo {0..19}

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

$ echo {00..19}

00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19


Looks like it also works with single letters.

$echo {A..D}

A B C D


Hmm, I'd always used the "seq" command for that...

$ echo `seq 0 19`

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19


Perl is very much like this too.

$ perl -le 'print join(" ", "00".."20")' 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20


wow, genius!

(the second doesn't work on older versions of bash, like macos)


Well, using Bash. A lot of these tricks aren't portable so you'll have fun when your scripts break on e.g. Dash (Ubuntu).


Also works on zsh and fish, though fish does not enumerate in the same order. Indeed does not work on sh.

Thanks for the heads up.

Too bad it's not portable, but I guess this is mainly useful in an interactive shell.

I mostly use #!/usr/bin/env sh, so my scripts will remain free of shell Cartesian products and other brace expansions.


It's also inside Perl as bsd_glob().

  use File::Glob ':bsd_glob';


That's exactly why that works, the shell expands it, so

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

    mv foo-bar-baz.txt foo-bar-quux.txt


Shell expansion into the two strings and the order you mentioned. These two strings are passed along the argument vector to the mv command.


The { .. } stuff expands regardless of whether it matches files.

Unlike *, ? [a-z] ...


Exactly. Speaking of which, how do you make a tarball of a directory?

    tar czf verylongdirectoryname{.tar.gz,}
Feel feel to replace czf with cjf for bz2, or cJf for xz.


or with caf for any of them.


I much prefer

    rename -n 's/baz/quux/' foo-bar-*


This is such an awesome bash feature. Makes it so easy to generate variations of names. What is it called?


One of my pet peeves about expressive, terse syntaxes like this is that the features are not Google-able. Entering {} or !#:1 or !? in the search bar is more like swearing than like learning. This one happens to be called "Brace Expansion".

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


Protip: for difficult to Google syntax, add "" and `site:stackoverflow.com` to your search.


OR site:superuser.com


Google seems to ignore my punctuation either way.




This feature is brace expansion.


you can also create a bunch of directories that way. Or anything really.

mkdir /var/{log,spool,asdf,bar}


I came to this thread hoping someone wrote exactly what you did, otherwise I was going to do it myself. Thanks

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


Minor nitpick for the second case:

    mv foo-bar{,-baz}.txt


Good catch; updated


I tend to use tmux for this. Once you are proficient it is much easier to cut/paste without taking your hands from the keyboard. Admittedly the learning curve is way steeper than some bash expansions and/or a simple rewrite function.


This doesn't work to change a file name to something completely different, while you can do that using the posted gist, so there's a necessity for it to not re-type the path to the file twice.


TIL about brace expansion, thanks!

(also "namsral" in the GitHub gist comment section beat you to the punch)


mv is scary, though. It's one of the commands that can easily lead to data loss if you have a misplaced space or asteriks.


Do people ever type all this obscura in any reality? Seems a bit ridiculous to me.


I do that all the time. It's not particularly obscure: your shell was designed to help you do stuff like this.


Almost every day.

This syntax is no more obscure than a link in markdown, for example.


Benefits are derived from optimizing common tasks. If you commonly use use the shell, it's worth learning how to use it efficiently.

If you don't use it frequently, your are likely to forget it and it's not worth optimizing.


Seems like some deliberate practice in the shell might be a productive use of your time.


Fortunately for OP, the HN crowd already discussed exactly this. https://news.ycombinator.com/item?id=19988548


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"


I've been using bash/zsh for 18 years and did not know about ctrl-W, ctrl-Y. This might be a game changer for me!


Ctrl-W is the standard default character for erasing a word in the POSIX TTY cooked mode. Thus it works even when using programs that don't have a line editor. Ctrl-U similarly erases the whole line.

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.


getpass supports readline shortcuts? TIL


Is my comment not clear? They are not "readline shortcuts"; readline got them from Unix. GNU targeted Unix as the system to replace with free software and adopted its conventions.

Beside Ctrl-W and Ctrl-U, another convention from the Unix TTY found in readline is Ctrl-D.

getpass doesn't support editing at all; it runs the TTY in "cooked mode", just with echo disabled. The operating system kernel implements the rudimentary editing (Ctrl-W and Ctrl-U).


Note: ^T is also a very useful command bound by default to "swap the character under the cursor and the previous one". That is, `sl` followed by left arrow, ^T, produces "ls".


GNU readline is always surprising to me, being a Vi guy I almost always `C-x C-e` to edit my command with, you guessed it right: {,n}vi{,m}. But it seems that just taking the time to learn readline will be a very big boost in productivity.


You can add 'set -o vi' to your bashrc to enable a sort of vim emulation. Pressing Esc will take you to command mode, where you can use commands like b, w, e, 5x, i. Ctrl-w and ctrl-y still work as described here.

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.


I'm happy enough with `set editing-mode vi` in ~/.inputrc (for bash) and `plugins=(vi-mode)` in ~/.zshrc (for zsh).


Doesn't work if the filename contains spaces:

    # mv "Foo bar" _


No but the manual method with Ctrl-W still works. Multiple consecutive Ctrl-W operations add to the clipboard; you can gobble the whole thing with several Ctrl-W and regurgitate two copies with Ctrl-Y Ctrl-Y.

If you like spaces in filenames, you should use a GUI, anyway.

I recommend Windows Explorer; it's widely available.


Doesn't work for me if the filename has underscore(_) or dot (.) - it only copies part of the filename.


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

:D


Ctrl-W Ctrl-W Ctrl-Y Ctrl-Y will work.


I would prefer to use brace expansion after learning about it today, over this.


Brace expansion won't work if you need to make edits in multiple places.


Well, it could work if we have a function to pick off the first and last combination from the Cartesian product, haha.

We define:

  # print first and last argument
  fl() {
   local a=("$@");
   printf "%s %s\n" "${a[0]}" "${a[${#a[@]} - 1]}"
  }
Now:

  $ fl {a,b}--{c,d}--{foo,bar}--{x,y}--{m,n}
  a--c--foo--x--m b--d--bar--y--n
We can use this using command substitution, or the old backticks:

  $ mv $(fl path/{from,to}/subdir/{foo,bar}.png)
There we go; edits in multiple places.


I use escape-. a lot


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.


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


The GNU readline solution is neat though.


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.


This. When I figured out you could edit the directory listing like a file and then have Emacs apply those edits I felt like I had acquired superpowers.

Actually I generally feel like I have superpowers when I use Emacs. The feeling was stronger than usual that day.


vidir + vi/ed does the same. It puts the directory as a text buffer, with an entry per line.


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


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?


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


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


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.


> 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) that it's just 'v' in normal mode.


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


This might be the compromise which unites all camps:

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


Alt+E in fish shell in case someone's running it in place of bash.


This is my new favorite bash trick. Thanks!


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.


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 ;-) )


This is also why I cringe when people suggest to alias `rm` to `rm -i`. That will bite you, believe me.


heh :) youre right


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.


Cunningham's Law


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


I can't believe I missed that opportunity!!


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.


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.


i always run mv -i to make sure i don't accidentally overwrite an existing 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.


I double check the filenames instead, because many of the tools I work with don't have -i flags.


I’ve done

  gcc foo.c -o foo.c
far too many times :(


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


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


I work in exactly two modes of `gcc` usage. I either accept `./a.out` as the name I deserve, or I write a `CMakeLists.txt`.

There nothing in between.


In ZSH I do:

mv foo-bar <alt>-m

It’ll repeat foo-bar. It’s very useful. I miss it when I’m using Fish or Bash.


In bash, you can do ctrl-w ctrl-y ctrl-y to cut paste paste as long as it doesnt have spaces


I do this too, but sometimes its just too many tabs


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


Link: https://www.nongnu.org/renameutils/

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


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.



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.

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


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.


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.


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


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)


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


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.


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


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


If I understand correctly, yes, that's how I'd describe it.


that's a good tip.

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)


Lets see, I hope not :) I changed it only for when you call it with just 1 argument, which is not valid normally. Otherwise it calls the original mv.


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


nice, I didn't know about this


Those keybindings belong to GNU readline https://en.m.wikipedia.org/wiki/GNU_Readline


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

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.


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.


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


Nice, feels like Windows File Explorer ;D


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

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


That was the point! But I'm learning so many other ways to rename here in comments :)


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


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


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.


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


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



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!


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.


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.


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

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!


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


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


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


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


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


I rename a single file much more often


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:

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


Yup, readline's yank-last-arg command Alt-. or Alt-_ (see https://www.gnu.org/software/bash/manual/html_node/Commands-...) 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-.)


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


Is that the same thing as ALT-. ?


Yes. It's also the same as Alt-_


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.


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


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


"without typing the name two times"

Is that pun intentional? It's hilarious.


or... you can do this

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

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


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


Shout out to visit(1) for lots of renames


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


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


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


Compared to what, though?


Exactly what I was thinking. As if Windows Explorer and Finder are so perfect themselves.


In this case Finder wins pretty easily IMHO. "Enter" to rename, edit in place, "Enter" to commit ("Esc" to cancel).


There's a whole lot of ??? in that edit in place.

For me, it usually goes like: <click> okay, check that I'm really editing. Crap, I'm not, I started a drag. <click> Okay, got lucky and it looks like I'm really in edit mode. Type a character. Oh crap, some of it I wanted to keep was selected, and now it's gone. Hit escape. Try again. <click> Crap, dragged it again. <click> Okay, editing. Carefully click again to clear the default selection. Carefully click again to put the cursor where I want to edit. Carefully type in the new name. Hit enter. Whew.

What could be easier?


I've never used a Mac but on both Windows and Linux all graphical file explorers I've used have used F2 for rename (I think it even means rename in some other programs that don't deal with files) and especially with the visual feedback there's never any confusion about whether you've started the rename operation. I also don't think I ever have a problem with accidentally starting a drag - again, perhaps a Mac problem, maybe with too small of a pixel count before starting a drag?

Realistically, some things are better done on the command line and some are better done in GUIs and this is just something much better done in a GUI. Of course if you are already in the command line then the overhead of switching to a totally different program is huge compared to the saving once you get there. But I find many sequences of simple file operations are easier in a GUI than the command line, and it's just as silly to religiously rule out GUIs as it is to never use the command line.


i agree with your rant. that is what makes guis inconvenient for that sort of task, but it's missplaced as the 'enter' should already put you into edit mode, so no messing with mouse clicks.


if you add the action of 'selecting the file name', the number of user specified operations is the same:

- <specify rename operation> : type mv or type enter

- <specify source file> : type file name or select file

- <specify destination file> : enter/edit new file name

- <commit> : enter to commit in finder, enter to run in shell


Where Finder/Explorer really fall flat is for commands on multiple files. Shift/Ctrl/Command clicking of files is painful with long lists. Especially when the list is longer than the UI window can display.


but "command" implies you know what you want to do, and you want to directly do it.

It's like going into a restaurant and ordering, without needing a menu.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: