Bash – Alphabetize words within filenames using sort

bashrenamesort

When reading tutorials on batch-renaming files in bash and using the sort command to sort file contents, I have not been able to figure out how to combine the two.

I have a directory whose contents are sorted using tags within the filename, similar to how the program TagSpaces handles things. I add whatever tags I can think of to the end of the filename when I create it or download it. Here's an example:

Sunrise (2) #wallpaper #4k #googleimages.jpg

Now I want to go through all these files and rename them so the tags are sorted alphabetically, without affecting anything before or after the tags (e.g. a picture's title or file extension). So the above would become:

Sunrise (2) #4k #googleimages #wallpaper.jpg

How do I accomplish this? I can't even figure out how to pass a file's name, and not its contents, to a command like sort, whose output I could then perhaps pipe to mv.

Best Answer

#!/bin/bash

for i in dir_for_files/*; do
    filename=${i%%#*}
    sorted_tags=$(grep -o "#[^ .]*" <<< "$i" | sort -n | tr '\n' ' ')
    ext=${i#*.}
    echo mv "$i" "${filename}${sorted_tags% }.$ext"
done

Testing:

##### Before sorting #####    
$ ls -1 dir_for_files
Note (3) #textfile #notes #important.txt
Sunrise (2) #wallpaper #4k #googleimages.jpg
Sunset (2) #wallpaper #2k #images.jpg

$ ./sort_tags.sh

##### After sorting #####
$ ls -1 dir_for_files
Note (3) #important #notes #textfile.txt
Sunrise (2) #4k #googleimages #wallpaper.jpg
Sunset (2) #2k #images #wallpaper.jpg
Related Question