How to replace a folder that's name is a date i.e. YYYYMMDD with folder hierarchy of year, month, date? I have a list of folders which have dates for names. The dates are in the format YYYYMMDD (e.g. 20150129). Within these folders are text documents which are related to that specific date.

I would like to restructure them in a folder hierarchy going from year to month to date, and to move the text documents into the corresponding 'date' folder lower down in the hierarchy.

In other words I would like the 'root' folder to be named after the year like 2015, and then create sub-folders named with months like 01, and then create further sub-folders named with dates like 29 which hold the corresponding text documents.

So the path would look like 2015/01/29/file.txt or 2015&gt;01&gt;29&gt;file.txt.

I have taken a look at Automator and it seems that something like this is not possible although I could be wrong, so I would like to know...


Is there some easy solution to this problem that any layman can understand, for example an Automator workflow, or does this require some understanding of terminal commands and regular expressions?
How would one solve this problem provided there is in fact a solution?
You can use the following in Terminal. cd to the containing folder, then run the following:

find . -type f -exec bash -c \
  'F=$(sed -E "s#^\./([0-9]{4})([0-9]{2})([0-9]{2})#\1/\2/\3#" &lt;&lt;&lt; $1);\
  mkdir -p -- $(dirname "$F");\
  mv -- "$1" "$F"' - {} \;


find . -type f obtains every file in the current directory recursively.
-exec bash -c opens a shell to run the following commands.
F=$(…) opens a subshell and uses sed on the file path to manipulate the path into the folders.
^\./([0-9]{4})([0-9]{2})([0-9]{2}) is a regex with three capture groups, as follows:

\1/\2/\3 is replacement, where each capture group (\1, etc) are separated by /.
mkdir -p -- $(dirname "$F") creates the directories to move the files into.
mv -- "$1" "$F" moves each file into its corresponding folder.

This takes the hierarchy on the left and converts it to the hierarchy on the right:




├── 20170201               └── 2017
│   └── abcdefghij             ├── 02
└── 20170302                   │   └── 01
    └── abcdefghij 2           │       └── abcdefghij
                               └── 03
                                   └── 02
                                       └── abcdefghij 2


If there are other files in the containing folder with a date as a name, they will be moved as if they are a folder. To prevent this, replace the second line with:

  'F=$(sed -E "s#^\./([0-9]{4})([0-9]{2})([0-9]{2})(?:/.+)#\1/\2/\3#" &lt;&lt;&lt; $1);\


The (?:/.+) ensures that the path has a subsequent component, therefore ignoring anything without a child in the parent directory which are files.