I\'m running macOS and looking for a way to quickly sort thousands of jpg files. I need to create folders based on part of filenames and then move those files into it.
I would back up the files first to somewhere safe in case it all goes wrong. Then I would install homebrew and then install rename
with:
brew install rename
Then you can do what you want with this:
rename --dry-run -p 's|(^[^_]*)|$1/$1|' *.jpg
If that looks correct, remove the --dry-run
and run it again.
Let's look at that command.
--dry-run means just say what the command would do without actually doing anything
-p means create any intermediate paths (i.e. directories) as necessary
's|...|' I will explain in a moment
*.jpg means to run the command on all JPG files.
The funny bit in single quotes is actually a substitution, in its simplest form it is s|a|b|
which means substitute thing a
with b
. In this particular case, the a
is caret (^
) which means start of filename and then [^_]*
means any number of things that are not underscores. As I have surrounded that with parentheses, I can refer back to it in the b
part as $1
since it is the first thing in parentheses in a
. The b
part means "whatever was before the underscore" followed by a slash and "whatever was before the underscore again".
Using find
with bash Parameter Substitution in Terminal would likely work:
find . -type f -name "*jpg" -maxdepth 1 -exec bash -c 'mkdir -p "${0%%_*}"' {} \; \
-exec bash -c 'mv "$0" "${0%%_*}"' {} \;
This uses bash Parameter Substitution with find
to recursively create directories (if they don't already exist) using the prefix of any filenames matching jpg
. It takes the characters before the first underscore (_
), then moves the matching files into the appropriate directory. To use the command simply cd
into the directory you would like to organize. Keep in mind that without using the maxdepth
option running the command multiple times can produce more folders; limit the "depth" at which the command can operate using the maxdepth
option.
${parameter%word}
${parameter%%word}
The word is expanded to produce a pattern just as in filename expansion. If the pattern matches a trailing portion of the expanded value of parameter, then the result of the expansion is the value of parameter with the shortest matching pattern (the ‘%’ case) or the longest matching pattern (the ‘%%’ case) deleted.
↳ GNU Bash : Shell Parameter Expansion