linux – Copy and Rename Using Nested Wildcards

bashlinuxshell-script

I have the following file structure:

raw:
    F1:
        file1.pdf
    F2:
        file2.pdf
    (...)
pdf:
    (...)

There is always exactly one pdf file per folder, and the file/folder names could be arbitrary.

I want to copy all pdf files in the raw directory to the pdf directory and replace their filenames with their root folder names. For the example above this would be the result:

raw:
    F1:
        file1.pdf
    F2:
        file2.pdf
    (...)
pdf:
    F1.pdf
    F2.pdf
    (...)

I have read about wildcard copying, but this is obviously a problem because I would have to use two nested wildcards to copy my files. So this obviously does not work:

cp raw/*/*.pdf pdf/*.pdf

Is there a way around this or do I have to loop over my folders and use regex to split the paths?

Best Answer

Use nested loops:

shopt -s nullglob  # To prevent failures if there's no pdf in a dir.
for dir in raw/* ; do
    for pdf in "$dir"/*.pdf ; do
        cp -- "$pdf" pdf/"${dir#raw/}".pdf  # Remove the "raw/" part
    done
done

or iterate over the files and apply the parameter expansion twice to generate the target name:

for pdf in raw/*/*.pdf ; do
    target=${pdf#raw/}  # Remove the "raw/" part
    target=${target%/*}  # Remove the filename
    cp -- "$pdf" pdf/"$target".pdf
done
Related Question