Inserting text in file names while copying them.

I'm trying to find a Bourne shell script that will copy files from one directory using a wild card for the file name (*) and add some more characters in the middle of the file name as it is copied. As an example:

/u01/tmp-file1.xml => /u02/tmp-file1-20130620.xml
/u01/tmp-file2.xml => /u02/tmp-file2-20130620.xml
/u01/tmp-file3.xml => /u02/tmp-file3-20130620.xml
/u01/tmp-file4.xml => /u02/tmp-file4-20130620.xml

I've seen scripts where you can append characters to the end of a file or to the front of a file, but not in the middle of the file name. I was hoping for something as easy as:

cp /u01/tmp-file*.xml /u02/tmp-file*-20130620.xml

but of course no such thing exists.

You could use a for loop with parameter substitution:

#!/bin/bash

DT=$( date +"%Y%m%d" )

for file in /u01/tmp*.xml
do
        fname="${file##*/}"
        fname="${fname%.xml}"
        fname="${fname}-${DT}.xml"
        echo cp $file /u02/$fname
done

Remove the highlighted echo if output looks good.

 
#!/bin/bash

DT=$( date +"%Y%m%d" )

for file in /u01/tmp*.xml
do
        fname="${file##*/}"
        fname="${fname%.xml}"
        fname="${fname}-${DT}.xml"
        echo cp $file /u02/$fname
done
 
 

Hello Yoda,

Could you please explain the code please it will be more useful for us.

Thanks,
R. Singh

Check Parameter Expansion to better understand the syntax:

DT=$( date +"%Y%m%d" )

# for each file in /u01/tmp*.xml
for file in /u01/tmp*.xml
do
        # Remove every character before the last /
        fname="${file##*/}"
        # Remove .xml
        fname="${fname%.xml}"
        # Construct new file name
        fname="${fname}-${DT}.xml"
        echo cp $file /u02/$fname
done
1 Like

This is great if I know what the suffix is. I was looking for more generality by being able to replace the wild card with some text and leave the rest of the file name as is. So let's call the new function cpr (copy with replace). With the same file set:

/u01/tmp-file1.xml => /u02/tmp-file1-20130620.xml
/u01/tmp-file2.xml => /u02/tmp-file2-20130620.xml
/u01/tmp-file3.xml => /u02/tmp-file3-20130620.xml
/u01/tmp-file4.xml => /u02/tmp-file4-20130620.xml

I should be able to:

cpr /u01/tmp*.xml /u02/tmp*-20130620.xml

or in a more generalized:

cpr [dir1]string1*string2 [dir2]string1*string3

so that every matching string in parameter1 is duplicated in parameter2 on the output, but string3 is inserted in the name. So the command might be:

cpr /u01/tmp*.xml /u02/tmp*-20130620.txt 

and the result would be:

/u01/tmp-file1.xml => /u02/tmp-file1-20130620.txt
/u01/tmp-file2.xml => /u02/tmp-file2-20130620.txt
/u01/tmp-file3.xml => /u02/tmp-file3-20130620.txt
/u01/tmp-file4.xml => /u02/tmp-file4-20130620.txt

After many tries at parameter expansion I can see why the cp command doesn't allow this.

Hi.

I've used mved at mved a few times.

I have not looked at your problem in detail to see if mved would solve it, but it might be worth a glance.

Best wishes ... cheers, drl

Or switch to zsh :slight_smile:

zsh-5.0.2[t]% autoload -U zmv
zsh-5.0.2[t]% ls -l ./u01
totale 0
-rw-r--r-- 1 Master None 0 21 giu 14.35 tmp-file1.xml
-rw-r--r-- 1 Master None 0 21 giu 14.35 tmp-file2.xml
-rw-r--r-- 1 Master None 0 21 giu 14.35 tmp-file3.xml
-rw-r--r-- 1 Master None 0 21 giu 14.35 tmp-file4.xml
zsh-5.0.2[t]% zmv -nv -- './u01/tmp(*).xml' './u02/tmp$1-20130620.txt'
mv -- ./u01/tmp-file1.xml ./u02/tmp-file1-20130620.txt
mv -- ./u01/tmp-file2.xml ./u02/tmp-file2-20130620.txt
mv -- ./u01/tmp-file3.xml ./u02/tmp-file3-20130620.txt
mv -- ./u01/tmp-file4.xml ./u02/tmp-file4-20130620.txt