I’ve created a rough script to get you started. I haven’t tested it thoroughly, so report/debug any errors you encounter and I’ll see if I can recreate them.
Here is the sample text file that I created for the purposes of my testing, which I named folders.dat:[format]Folder 1
Folder 2
Folder 2A
Folder 2A(i)
Folder 2A(ii)
Folder 2B
Folder 3
Folder 4
Folder 4A
Folder 4B
Folder 4B(i)
Folder 4B(i)a
Folder 4C
Folder 4C(i)
Folder 5
Folder 5A
Folder 5B
Folder 5C[/format]The leading whitespaces are tabs, where one additional tabstop difference between two consecutive lines represents a child folder located inside the folder on the line above it. I would suggest that, for now, you adhere to this strictly, as I have not gone as far as to build in safeguards to cater for malformed or unpredictable degrees of indentation, e.g. a folder indented two tabstops ahead of the one before it does not make sense.
-----------------------------------------------------------------------------------------------------------------------------
--HANDLERS & SCRIPT OBJECTS:
--ascend
-- Takes a path and returns an HFS path to the containing folder +N levels
-- above
to ascend from dir by N : 1
local dir, N
if dir starts with "~/" then set dir to the ¬
contents of [system attribute "HOME", ¬
text 2 thru -1 of dir] as text as ¬
POSIX file as text
if N = 0 then return dir
set dir to POSIX path of ([dir, ":"] as text) ¬
as POSIX file as text
ascend from dir by N - 1
end ascend
--mapItems
-- Applies a +function (handler) to every item in a list, +L, modifying the
-- original list and returning the result as the return value as well
to mapItems from L as list given handler:function
local L, function
script
property list : L
end script
tell (a reference to the result's list)
repeat with i from 1 to its length
set x to (a reference to its item i)
set x's contents to function's ¬
fn(x's contents, i, it)
end repeat
end tell
L
end mapItems
--folderTree
-- Reads a +textfile that contains a tab-indented map of a folder hierarchy
-- and creates the directory structure in the +root folder
on folderTree from textfile at root
local textfile, root
tell application "System Events" to set textfile ¬
to the POSIX path of the file named textfile
--:[untab]
-- Eliminates leading tabstops and saves the count against folder name
script untab
on fn(x)
script
to untab(x, |ξ|)
if {} = x's words then return false
if x's first character ≠ tab ¬
then return {|ξ|, x}
untab(x's text 2 thru -1, 1 + |ξ|)
end untab
end script
result's untab(x, 0)
end fn
end script
--:[branch]
-- Replaces folder names with paths to map intended folder locations
script branch
property sys : application "System Events"
property dir0 : path of sys's item root
on fn(x, i, L)
if i = 1 then return {0, contents of ¬
[dir0, x's item 2, ":"] as text}
set {N, dirN} to x
set {M, dirM} to L's item (i - 1)
if N = 0 then
[dir0, dirN, ":"]
else if N ≠ 0 then
if N > M then
[dirM, dirN, ":"]
else if N = M then
[ascend from dirM, dirN, ":"]
else if N < M then
set A to M - N + 1
[ascend from dirM by A, dirN, ":"]
end if
end if
set dirN to the result as text
{N, dirN}
end fn
end script
--:[restOf]
-- Discard tab counts and return a flattened list of folder paths
script restOf
on fn(x)
x's end
end fn
end script
--:[makedir]
-- Given a folder path, create the folder
script makedir
on fn(x)
set text item delimiters to ":"
set dir to x's text items 1 thru -3 as text
set fldrname to x's text item -2
tell application "System Events"
make new folder at folder dir ¬
with properties ¬
{name:fldrname}
end tell
end fn
end script
read the textfile using delimiter linefeed
mapItems from the result given handler:untab
mapItems from the result's lists given handler:branch
mapItems from the result given handler:restOf
mapItems from the result given handler:makedir
end folderTree
-----------------------------------------------------------------------------------------------------------------------------
--IMPLICIT RUN HANDLER:
folderTree from "~/Desktop/folders.dat" at "~/Example"
-----------------------------------------------------------------------------------------------------------------------------
It’s by no means the most efficient script and I would, at some point, like to merge the four separate calls to mapItems into a single call. However, it literally went straight from my brain out into the editor, so it’s evident how linearly I approached the problem and how unpolished the methodology remains.
A single handler call at the bottom of the script is where the process initiates. All of my handlers in this script use labelled parameters. folderTree takes two: the from parameter is where you specify the text file from which to read the tab-indented folder map; the at parameter is where you specify the location at which this new folder hierarchy is to be created. Abbreviated posix paths are fine; and HFS paths and alias objects are probably also fine.
[format]AppleScript: 2.7
Operating System: macOS 10.13[/format]