1

I have some directories named FOO and BAR and etc. that have files in form

  • FOO/
    • 1.png
    • ...
    • 18.png
  • BAR/
    • 1.jpg
    • ...
    • 12.jpg
  • ...

and I would like them to be all copied into the DESTINATION directory such that

  • DESTINATION/
    • 1.png
    • ...
    • 18.png
    • 19.jpg
    • ...
    • 30.jpg
    • ...

I am looking for a bash alias or function that does this.
the input should be something like function DESTINATION FOO BAR etc
if having destination directory makes the function too complicated, then please answer with the function treating the current directory as destination such so function FOO BAR etc

I made the below script for now, it works fine but only if all pictures are png and if there is no whitespace in the folder names.
if anyone has any suggestions on how to fix these bugs or how to improve the code in any way, please tell me.

#!/bin/bash
counter=1;
destination=$1;
for folder in "${@:2}"
do
    for picture in $folder/*.png
    do
        cp $picture $destination/$counter.png; 
        let counter=counter+1;
    done
done

1 Answers1

0

it works fine but only if all pictures are png and if there is no whitespace in the folder names.

The latter flaw is a common one, the solution is known: quote right. Get used to double-quoting.

To make the script work well with multiple extensions, enable nullglob, nocaseglob and (most importantly) extglob; then use a pattern like *.@(jpg|png|bmp).

To identify the extension later, use ${parameter##*.}.

The below code also uses -- for cp, in case any $folder expands to a string starting with -.

Your script will become this:

#!/bin/bash
shopt -s extglob nullglob nocaseglob
counter=1
destination="$1"
for folder in "${@:2}"
do
    for picture in "$folder"/*.@(jpg|jpeg|png|bmp|gif|tiff)
    do
        cp -- "$picture" "$destination/$counter.${picture##*.}" 
        let counter=counter+1;
    done
done

Note that the order of results from * in a globbing pattern (like your *.png or our *.@(jpg|jpeg|png|bmp|gif|tiff)) depends on LC_COLLATE, but it's always lexicographic (I mean in Bash, e.g. Zsh can be smarter). GUI file managers may care about numbers and sort 1.png before 18.png, but our script will sort 18.png (from a source directory like your FOO) before 1.png. This means in your example the file DESTINATION/1.png will be a copy of FOO/11.png, not of FOO/1.png.

Your original script was similarly "flawed", still you did not see this as a problem, so my script does not attempt to "fix" this.