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
  • We're not a script-writing site. What have you tried and where are you stuck? – harrymc Mar 18 '24 at 09:46
  • oh sorry, didn't know that. back at askubuntu, they usually helped me so I got used to asking on stackoverflow for scripting help. do you know any forums that can help with bash scripting? doesn't have to be a stackoverflow forum. – user3446323672 Mar 18 '24 at 11:27
  • And if you do expect help, show the logic you'd use to number the files -- how would you resolve two 1.jpg file names? If the end file names are irrelevant, just number the output consecutively, whatever the input file name. I.E., FOO/able.jpg ->1.jpg, FOO/baker.jpg ->2.jpg, BAR/baker.jpg->3.jpg, usw... – DrMoishe Pippik Mar 18 '24 at 12:30
  • the logic is, the first folder's 1-n pictures will be the 1-n pictures and second folders 1-m pictures will be the n+1 - n+m pictures and so on and so forth. all original folders have files with names in format #.ext – user3446323672 Mar 18 '24 at 19:59
  • It's not that you can't ask scripting questions, but that we are not a service, so we expect you to have begin the process of writing that script yourself, and then come with THAT effort and information here so that we can help you get past whatever problem you haven't been able to solve. – music2myear Mar 18 '24 at 20:01
  • ok I made a script that has a few bugs, below. please take a look at it. – user3446323672 Mar 19 '24 at 07:30
  • Hello again, I am almost at the desirable answer, my current problem is that the extension filtering pattern ignores what extension the files have, if you all can take a look, i would greatly appreciate it. – user3446323672 Mar 30 '24 at 01:09
  • @user3446323672 I reverted the question to the revision that is answered. In the future, please do not substantially change requirements after getting answer(s). You can see your edits in the revision history, so if you want to turn them into a new question, you can copy from there. – Kamil Maciorowski Mar 30 '24 at 07:46

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.

  • Hello. I was out of town so I didnt see your reply. I made some alterations to fix the sorting issue, it works now but it copies all files not just the ones with extensions specified in *.@() other than that it works fine now. if you can take a look and see if you have any ideas on the extension fix then it would be great. – user3446323672 Mar 30 '24 at 01:06
  • @user3446323672 Please do not turn your question into a chameleon. Your original script does not keep the order of files and you did not state it was a problem. Now you're introducing a requirement not present in the original post. One problem per question please. Whatever is the problem now, it's a new problem, so consider asking a new question. (you can link to the above question to provide context). – Kamil Maciorowski Mar 30 '24 at 07:41
  • my question in english demands order be kept, while my script had logic bug that did not keep order. for now I am going to accept this answer and open a new question, asking for the sorting feature as you recommended. – user3446323672 Mar 31 '24 at 03:43
  • @user3446323672 "my question in english demands order be kept" – Not "kept", not "the same order", but "in correct order". The phrase "in correct order" is vague until you define the correct order. You did not define it explicitly, only by the script that allegedly "works fine but…" and none of the "buts" is about the order; so this seemed the order that "works fine" (if not the desired order then at least an acceptable order). I'm going to try to answer the new question. The more strictly it defines the truly correct order, the better. – Kamil Maciorowski Mar 31 '24 at 06:02