jlconlin
jlconlin

Reputation: 15064

Copy and Rename Multiple Files with Regular Expressions in bash

I've got a file structure that looks like:

A/
    2098765.1ext
    2098765.2ext
    2098765.3ext
    2098765.4ext
      12345.1ext
      12345.2ext
      12345.3ext
      12345.4ext

B/
    2056789.1ext
    2056789.2ext
    2056789.3ext
    2056789.4ext
      54321.1ext
      54321.2ext
      54321.3ext
      54321.4ext

I need to rename all the files that begin with 20 to start with 10; i.e., I need to rename B/2022222.1ext to B/1022222.1ext

I've seen many of the other questions regarding renaming multiple files, but couldn't seem to make it work for my case. Just to see if I can figure out what I'm doing before I actually try to do the copy/renaming I've done:

for file in "*/20?????.*"; do
    echo "{$file/20/10}";
done

but all I get is

{*/20?????.*/20/10}

Can someone show me how to do this?

Upvotes: 12

Views: 20236

Answers (5)

William Pursell
William Pursell

Reputation: 212424

The glob behavior of * is suppressed in double quotes. Try:

for file in */20?????.*; do
    echo "${file/20/10}";
done

Upvotes: -1

Virgil Ming
Virgil Ming

Reputation: 559

Just wanna add to Explosion Pill's answer. On OS X though, you must say

mv "${file}" "${file_expression}"

Or the mv command does not recognize it.

Upvotes: 1

Gilles Quénot
Gilles Quénot

Reputation: 185530

Brace expansions like :

{*/20?????.*/20/10}

can't be surrounded by quotes.

Instead, try doing (with Perl rename) :

rename 's/^10/^20/' */*.ext 

You can do this using the Perl tool rename from the shell prompt. (There are other tools with the same name which may or may not be able to do this, so be careful.)

If you want to do a dry run to make sure you don't clobber any files, add the -n switch to the command.

note

If you run the following command (linux)

$ file $(readlink -f $(type -p rename))

and you have a result like

.../rename: Perl script, ASCII text executable

then this seems to be the right tool =)

This seems to be the default rename command on Ubuntu.

To make it the default on Debian and derivative like Ubuntu :

sudo update-alternatives --set rename /path/to/rename

Upvotes: 0

Hai Vu
Hai Vu

Reputation: 40763

Here is a solution which use the find command:

find . -name '20*' | while read oldname; do echo mv "$oldname" "${oldname/20/10}"; done

This command does not actually do your bidding, it only prints out what should be done. Review the output and if you are happy, remove the echo command and run it for real.

Upvotes: 12

Explosion Pills
Explosion Pills

Reputation: 191779

You just have a little bit of incorrect syntax is all:

for file in */20?????.*; do mv $file ${file/20/10}; done
  1. Remove quotes from the argument to in. Otherwise, the filename expansion does not occur.
  2. The $ in the substitution should go before the bracket

Upvotes: 22

Related Questions