Sorry for the poor title. What I am trying to do is the following. I have a directory with (say) a 1000 files with names of the form Foo_bar_1,...,Foo_bar_1000. I would like to remove the 'bar' from each file name. For a single file this is easy, e.g.: mv Foo_bar_1 Foo_1.

Obviously I could process all files in this way using a loop. However, I am wondering if there is an easy way to do this without a loop using the mv command an regexps. I can match any source file with the expression Foo_bar_*. Is there any way I can now "access" the text that was matched with * ?

What I want to write is something like mv Foo_bar_* Foo_*, where the second * in the destination file should be equal to the string that was matched with * in the source file. How can this be done?


1 Answer 1


Wildcards are expanded by your shell before a command runs. So this will be executed:

mv Foo_bar_1 Foo_bar_2 ... Foo_bar_1000 Foo_bar_1 Foo_bar_2 ... Foo_bar_1000

or if you have files like Foo_foo_1, they will be added too as they match the second wildcard.

So no, it is not possible.

Also, mv does only accept a single target.

You can make a for loop:

for f in *; do mv "$f" "${f/_bar_/_}"; done

or use some batch rename tools for that:

Perl rename tool:

rename 's/_bar_/_/' *

"normal" rename tool:

rename '_bar_' '_' *

See also:

  • Thanks! Even though it could not be done with a single mv command, it was a very helpful answer. Also, thanks for the links. May 27, 2020 at 14:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .