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?


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 '20 at 14:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.