Home > Software design >  Batch copy and rename multiple files in the same directory
Batch copy and rename multiple files in the same directory

Time:10-19

I have 20 files like:

01a_AAA_qwe.sh
01b_AAA_asd.sh
01c_AAA_zxc.sh
01d_AAA_rty.sh
...

Files have a similar format in their names. They begin with 01, and they have 01*AAA*.sh format.

I wish to copy and rename files in the same directory, changing the number 01 to 02, 03, 04, and 05:

02a_AAA_qwe.sh
02b_AAA_asd.sh
02c_AAA_zxc.sh
02d_AAA_rty.sh
...

03a_AAA_qwe.sh
03b_AAA_asd.sh
03c_AAA_zxc.sh
03d_AAA_rty.sh
...

04a_AAA_qwe.sh
04b_AAA_asd.sh
04c_AAA_zxc.sh
04d_AAA_rty.sh
...

05a_AAA_qwe.sh
05b_AAA_asd.sh
05c_AAA_zxc.sh
05d_AAA_rty.sh
...

I wish to copy 20 of 01*.sh files to 02*.sh, 03*.sh, and 04*.sh. This will make the total number of files to 100 in the folder.

I'm really not sure how can I achieve this. I was trying to use for loop in the bash script. But not even sure what should I need to select as a for loop index.

for i in {1..4}; do
   cp 0${i}*.sh 0${i 1}*.sh
done

does not work.

CodePudding user response:

You can't do multiple copies in a single cp command, except when copying a bunch of files to a single target directory. cp will not do the name mapping automatically. Wildcards are expanded by the shell, they're not seen by the commands themselves, so it's not possible for them to do pattern matching like this.

To add 1 to a variable, use $((i 1)).

You can use the shell substring expansion operator to get the part of the filename after the first two characters.

for i in {1..4}; do
    for file in 0${i}*.sh; do
        fileend=${file:2}
        cp "$file" "0$((i 1))$fileend"
    done
done

CodePudding user response:

There are going to be a lot of ways to slice-n-dice this one ...

One idea using a for loop, printf brace expansion, and xargs:

for f in 01*.sh
do
    printf "%s\n" {02..05} | xargs -r -I PFX cp ${f} PFX${f:2}
done

The same thing but saving the printf in a variable up front:

printf -v prefixes "%s\n" {02..05}

for f in 01*.sh
do
    <<< "${prefixes}" xargs -r -I PFX cp ${f} PFX${f:2}
done

Another idea using a pair of for loops:

for f in 01*.sh
do
    for i in {02..05}
    do
        cp "${f}" "${i}${f:2}"
    done
done

Starting with:

$ ls -1 0*.sh
01a_AAA_qwe.sh
01b_AAA_asd.sh
01c_AAA_zxc.sh
01d_AAA_rty.sh

All of the proposed code snippets leave us with:

$ ls -1 0*.sh
01a_AAA_qwe.sh
01b_AAA_asd.sh
01c_AAA_zxc.sh
01d_AAA_rty.sh

02a_AAA_qwe.sh
02b_AAA_asd.sh
02c_AAA_zxc.sh
02d_AAA_rty.sh

03a_AAA_qwe.sh
03b_AAA_asd.sh
03c_AAA_zxc.sh
03d_AAA_rty.sh

04a_AAA_qwe.sh
04b_AAA_asd.sh
04c_AAA_zxc.sh
04d_AAA_rty.sh

05a_AAA_qwe.sh
05b_AAA_asd.sh
05c_AAA_zxc.sh
05d_AAA_rty.sh

NOTE: blank lines added for readability

  • Related