Scratching my own itch. I have a bunch of directories which I want moved into alphabetic sub-directories. This is handy is you have a bunch of MP3s, books, or other catalogued files.
This bash script moves a top level directory (and all the files and subdirectories under it), to a folder based on the (upper-case) version of the first character of the directory name.
#!/bin/bash
for dir in */ ; do
start=${dir:0:1}
mkdir -p ${start^^}
mv "$dir" ${start^^}
done
Save that as sort.sh, make it executable with chmod +x sort.sh and run with ./sort.sh
It turns this:
.
├── Adella
├── adrianna
├── Barb
├── bebe
├── Carleen
├── catherina
Into:
.
├── A
│ ├── Adella
│ ├── adrianna
├── B
│ ├── Barb
│ └── bebe
├── C
├── Carleen
├── catherina
How it works
Let's break this down to see what everything does
-
for dir in */ ; do - This loops through the current directory and finds every item which
ends
with a
/- that is, all directories
-
start=${dir:0:1} - Grab a sub-string from the directory name. In this case, the first character.
-
mkdir -p ${start^^} - Make a directory,
use the
-pflag to make sure we don't get an error when trying to create a duplicate directory . The^^command makes things upper case .
-
mv "$dir" ${start^^} - Move the directory we found into the newly created directory.
-
done - Finish the loop
Warnings
- Only works with folders - it won't move any files in your top level directory.
- Non-ASCII characters are supported. For example,
你好is sorted into你. - Handles directories with spaces, punctuation, and numbers at the start.
- No doubt there is some horrific bug lurking in those half-dozen lines. Be a friend and drop me a note in the comments, would you?
One thought on “Sort Folders Into Alphabetic Sub-Folders”
Andrew McGlashan
More fun, let's see if this works:
$ cat organize_files.sh #!/bin/bash sort_assoc_array() { for yr in ${years[@]} do echo $yr done|sort -n } declare -A years declare -a yrs file # collect files in top level directory to move files=( $(find . -maxdepth 1 -type f -name '20[01][0-9]*') ) # work out which year folders are needed for filex in ${files[@]} do dirx=${filex:2:4} [ ! -z ${years[$dirx]} ] || { echo add year $dirx years[$dirx]=$dirx } done # sort the years yrs=( $(sort_assoc_array) ) # create the year folders for yr in ${yrs[@]} do [ -d "$yr" ] || mkdir "$yr/" chown andrewm:andrewm "$yr/" done # move the files to their /year/ folder for filex in ${files[@]} do dirx=${filex:2:4} mv "$filex" "$dirx/" done # touch the year folder with the timestamp of the newest file for that year for yr in ${yrs[@]} do lastfileforyear=$(ls -rt ${yr}/|tail -1) touch -r "$yr/$lastfileforyear" "$yr/" done