Skip to content

Instantly share code, notes, and snippets.

@rg3915
Forked from vallahor/README.md
Last active January 13, 2024 04:27
Show Gist options
  • Save rg3915/fc6c26f4f796c551a1ac0f47908c3b7b to your computer and use it in GitHub Desktop.
Save rg3915/fc6c26f4f796c551a1ac0f47908c3b7b to your computer and use it in GitHub Desktop.
Given a txt file with a tree structure of directories/files generate a sh with necessary commands to generate that file tree

sh from txt contains tree structure of directories and files

How to create sh commands from txt file contains tree structure of directories and files?

This program convert tree structure of directories and files generate a sh with necessary commands to generate that file tree.

He read input.txt and convert to output.sh.

This is result:

$ tree -a
.
├── a
├── b
├── c
│   └── d
│       └── e
│           └── uau.txt
├── .gitignore
├── one
│   └── two
│       └── three
│           ├── five
│           │   └── six
│           │       ├── eight
│           │       └── seven
│           └── four
├── README.md
├── static
│   ├── css
│   │   ├── global
│   │   │   ├── global.css
│   │   │   └── root.css
│   │   └── styles.css
│   └── js
│       ├── main.js
│       ├── modules
│       │   └── work.js
│       └── timer.js
└── templates
    ├── about.html
    └── index.html
README.md
.gitignore
templates/
index.html
about.html
static/
css/
global/
global.css
root.css
styles.css
js/
main.js
timer.js
modules/
work.js
one/
two/
three/
four/
five/
six/
seven/
eight/
a/
b/
c/
d/
e/
uau.txt
mkdir -p {templates,static,one,a,b,c}
touch {README.md,.gitignore}
touch templates/{index.html,about.html}
mkdir -p static/{css,js}
touch static/css/styles.css
mkdir -p static/css/global/
touch static/css/global/{global.css,root.css}
touch static/js/{main.js,timer.js}
mkdir -p static/js/modules/
touch static/js/modules/work.js
mkdir -p one/two/three/{four,five}
mkdir -p one/two/three/five/six/{seven,eight}
mkdir -p c/d/e/
touch c/d/e/uau.txt
class Directory:
def __init__(self, name):
self.name = name
self.directories = []
self.files = []
self.created = False
def parse_dir(lines: list[str], dir_name: str, position: int = 0, indent: int = 0) -> (Directory, int):
dir = Directory(dir_name)
index = 0
while position + index < len(lines):
line = lines[position + index]
name = line.lstrip()
current_indent = len(line) - len(name)
if len(line) == 0:
index += 1
continue
if current_indent < indent:
break
if name[-1] == "/":
next_position = position + index + 1
cur_dir, idx = parse_dir(lines, name, next_position, current_indent + 1)
dir.directories.append(cur_dir)
index += idx
else:
dir.files.append(name)
index += 1
return dir, index
def gen_dir(lines: list[str]) -> Directory:
lines = [line.replace("\n", "").rstrip() for line in lines]
root_dir, _ = parse_dir(lines, "root")
return root_dir
def make_line(cmd: str, path: str, fields: list[str], end: str = "") -> str:
sep, lhs, rhs = "", "", ""
if len(fields) > 1:
sep, lhs, rhs = ",", "{", "}"
names = sep.join(fields)
return f"{cmd} {path}{lhs}{names}{rhs}{end}\n"
def gen_sh(dir: Directory, path: str = "") -> str:
mkdir = touch = txt = result = ""
if len(dir.directories) == 1:
directory = dir.directories[0]
result = gen_sh(directory, f"{path}{directory.name}")
else:
dir_names = []
if len(dir.directories) > 1:
for directory in dir.directories:
directory.created = True
dir_names.append(directory.name.replace("/", ""))
result += gen_sh(directory, f"{path}{directory.name}")
if not dir.created or len(dir_names) > 0:
mkdir = make_line("mkdir -p", path, dir_names)
if len(dir.files) > 0:
files_name = [file for file in dir.files]
touch = make_line("touch", path, files_name)
txt += f"{mkdir}{touch}{result}"
return txt
def main():
with open("input.txt", "r") as f:
lines = f.readlines()
root_dir = gen_dir(lines)
txt = gen_sh(root_dir)
with open("output.sh", "w") as f:
f.write(txt)
print(txt)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment