I'll confess, I've not had much practice with bash in a while, so this trivial exercise is serving as a reminder of the basics.
Nintendo organises the switch screenshots in an awkward way for casual viewing on a windows machine - the file structure is like this:
Note: (img).jpg is a unique string for each file.
Nintendo └── Album ├── 2019 │ └── 12 │ ├── 25 │ │ └── (img).jpg │ ├── 26 │ │ └── (img).jpg │ └── (etc) │ └── (etc) └── 2020 └── 01 ├── 01 │ └── (img).jpg ├── 02 │ └── (img).jpg └── (etc) └── (etc)
From this file stucture, you can see that it's a bit of a bother to view all the images in one go. Whilst I'm sure there's tools to do this already, it's a good learning opportunity, so here's my plan.
Put simply, I want to be able to type go to the root folder, 'Nintendo' - and be able to type one command to have all of the sub-directories collapse into the root folder; to flatten the subdirectories into the root directory. I want the file structure to go from the above, to this:
Nintendo ├── (img).jpg ├── (img).jpg ├── (img).jpg └── (etc)
Since the filenames of each image are unique, this shouldn't cause any filename conflicts.
The first step is to work out which file we're in, and store that as a variable - this will be the target directory for the files we're moving. This can be done using the command
target=$(pwd), setting the variable 'target' to store the current path.
My first approach for the next stage was to then store and parse the return of
ls -R - which would've given me a contents list of the current and all subdirectories, but someone called Greg wrote a blog post explaining "why you shouldn't parse the output of ls."
So instead, we're going to use the
find command, specifically
find -type f - as unline
ls, this is capable of returning a list of all files (and most usefully the paths of those files) in the current and sub-directories.
Now realistically, we don't want to do anything with the files in the target folder (where the command is executed from); by adding the option
-mindepth 2, we can exclude those files from the result.
Our final command for returning the list of all files in the current and subdirectories is therefore
find -mindepth 2 -type f.
And to put this into a nice loop to cycle through and move each file one at a time to the target directory:
for i in $(find -mindepth 2 -type f); do mv $i $target done
This does, however, leave us with one small problem of a bunch of empty subdirectories - that's easily fixed with one line of code using
find . -type d -empty -delete
Adding some nice lil echo statements to tell the user what the script is doing, and some code comments for good measure:
# get the current path target=$(pwd) #output moving files to target directory echo "Moving all files from subdirectories to" $target"." # cyclically move files to the target directory for i in $(find -mindepth 2 -type f); do mv $i $target done # go through and remove the empty directories find . -type d -empty -delete #output done echo "Done!"
This code should work regardless of filetype, or starting location; it should empty all subdirectories into the root it's executed from and then remove all of those empty subdirectories.
Executing it on my own Nintendo screenshots album seems to have worked, and if you're trying to do something similar, hopefully it worked for you too :)