Search code examples
bashfindcp

Copy specific files from different directories without changing file extension


I have a bunch of image files named as 1.jpg in several directories I want to copy that into another. I tried using the below command (consider 100 folders)

find folder/{1..100} -type f -name '1.*' -exec cp --backup=numbered "{}" folder/new/ \;

but the file extension get changed as below

1.jpg.~1~
1.jpg.~2~
1.jpg.~3~
...

I am expecting my output should look something like below

1.~1~.jpg
1.~2~.jpg
1.~3~.jpg
...

(or)

1(1).jpg
1(2).jpg
1(3).jpg
...

Note: I am using {1..100} so that folder order starts from 1, 2, 3, 4...100 and not as 1, 10, 11,...100, 2, 20, 21, 22...

Is there any way I could find and copy images without changing the file extension?

Thank you in advance!


Solution

  • Assuming you want to use the subfolder name (number) as a suffix to the new file name, would you please try:

    #!/bin/bash
    
    folder="folder"                 # directory name
    base="1"                        # basename of the jpg file
    ext="jpg"                       # extention of the jpg file
    new="new"                       # directory name for the "new" files
    
    mkdir -p "$folder/$new"         # create "new" directory if nonexistent
    
    while IFS= read -r -d "" f; do
        n=${f#*$folder/}; n=${n%/$base.$ext}
        echo cp -i -- "$f" "$folder/$new/$base($n).$ext"
    done < <(find "$folder" -type f -regex "$folder/[0-9]+/$base\.$ext" -print0)
    
    • find "$folder" -type f -regex "$folder/[0-9]+/$base\.$ext" finds all numbered folders which contains "1.jpg". You do not have to specify the range between 1 and 100.
    • -print0 option uses a null character to delimit filenames. It is useful to protect filenames which may contain special characters such as blank characters.
    • The output of find command, matched filenames delimited by null characters, is redirected to the read command within the while loop.
    • The -d "" option to the read command splits the input on null characters corresponding to -print0.
    • n=${f#*$folder/}; n=${n%/$base.$ext} assigns n to the subfolder name which contains the jpg file.
    • "$folder/$new/$base($n).$ext" constructs the new filename rearranging the substrings.

    If the output of the echo command looks okay, drop echo.