Well, @sylumer came in while I was away from my Mac and gave you the key information, which is that the find
command is the most natural way to get a list of files within a hierarchy of subfolders. But since I had a slightly different approach, I’ll give it to you, even though you now have a solution.
My solution is a pipeline, which I’ve written here with each component command on a separate line. The backslashes tell the shell to treat this as if it were typed out on a single line.
find '/Volumes/2018 Lacie/Images' -type f \
| sort --random-sort \
| head -n 20 \
| tr '\n' '\0' \
| xargs -0 -I '{}' cp {} '/Users/KillerRabbit/Documents/Random Images/'
I’m assuming the “Images” folder in your “2018 Lacie” disk contains all the subfolders of images you want to randomly select from, and I’ve taken “/Users/KillerRabbit/Documents/Random Images/” as the target folder.
If all of the files in the “/Volumes/2018 Lacie/Images” hierarchy are image files, the find
command will work as given above. If you have non-image files in there, you’ll want to add another restriction to limit the output:
find '/Volumes/2018 Lacie/Images/' -type f \( -iname "*.jpg" -o -iname "*.jpeg" \) \
| sort --random-sort \
| head -n 20 \
| tr '\n' '\0' \
| xargs -0 -I '{}' cp {} '/Users/KillerRabbit/Documents/Random Images/'
The -iname "*.jpg"
option does a case-insensitive search for files that end with “.jpg”, and the -iname "*.jpeg"
option does a case-insensitive search for files that end with “.jpeg”. The -o
between these two options tells find
to look for one or the other. This set of options is wrapped in escaped parentheses so find
treats this whole clause as a single thing. You could add a similar option for PNG files. Again, this addition isn’t needed if all the files are images.
You’ve been using head -n 1
to get just one image at a time, but based on your original description of the problem, I think you should copy as many images as you want into the target folder in a single command. That means giving head
’s -n
option the total number of files you want copied to the target folder. In the example above, I’m using 20.
The tr
command converts all the newline characters that separate the paths into nulls. This is a trick to make the xargs
command below work even when the files have characters that would otherwise screw it up.
Finally, the xargs
command runs the given cp
command for every line passed into it from head
. The -0
option tells xargs
that the items being passed to it are separated by nulls instead of newlines. The -I '{}'
option tells it to substitute in the path passed to it wherever it sees “{}”.
A Shortcut in which the user gets to enter the number of images that get copied to the target folder would look like this:
Note that the head
step in the pipeline is now head -n "$1"
and the Run Shell Script step gets its input from the Provided Input and passes it as an argument. Those are the adjustments needed to put the user input into the script.