Skip to main content
ignore non-folders in root
Source Link
grg
  • 205.6k
  • 45
  • 364
  • 495

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#" <<< $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#" <<< $1);\

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

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#" <<< $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

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#" <<< $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#" <<< $1);\

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

Retina'd screenshot
Source Link
grg
  • 205.6k
  • 45
  • 364
  • 495

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#" <<< $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: enter image description here
\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

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#" <<< $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: enter image description here
\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

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#" <<< $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
Added Explanation and Match Information frames from https://regex101.com so others have a better explanation of the RegEx used in the sed command.
Source Link
user3439894
  • 59.8k
  • 10
  • 112
  • 135

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#" <<< $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: enter image description here
\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

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#" <<< $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

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#" <<< $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: enter image description here
\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
end option list, remove echo
Source Link
grg
  • 205.6k
  • 45
  • 364
  • 495
Loading
more specifically match the start of the string in the regex
Source Link
grg
  • 205.6k
  • 45
  • 364
  • 495
Loading
added 243 characters in body
Source Link
grg
  • 205.6k
  • 45
  • 364
  • 495
Loading
Source Link
grg
  • 205.6k
  • 45
  • 364
  • 495
Loading