-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patha3
More file actions
executable file
·254 lines (223 loc) · 7.25 KB
/
a3
File metadata and controls
executable file
·254 lines (223 loc) · 7.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
#!/bin/bash
# ======================================================
# 🎋 asciitree - Zeigt die Baumstruktur eines Verzeichnisses
# Autor: Levogne
# Version: 1.2
# Beschreibung: Zeigt eine ASCII-Baumstruktur von Verzeichnissen und Dateien.
# Lizenz: MIT
# ======================================================
# Hilfe-Funktion
usage() {
cat <<EOF
🎋 asciitree - Zeigt die Baumstruktur eines Verzeichnisses
Autor: Levogne
Version: 1.2
Lizenz: MIT
Syntax:
a3 [OPTION] [VERZEICHNIS]
a3 <projekt-typ>
Optionen:
-h, --help Zeigt diese Hilfe an
-a, --all Zeigt Verzeichnisse und Dateien an, inkl. versteckte Dateien
-v, --version Zeigt die Skriptversion an
-[0-9] Zeigt die Struktur bis zur angegebenen Tiefe (z. B. -2)
--exc ORDNER1,ORDNER2 Schließt bestimmte Ordner von der Anzeige aus
--export DATEI Exportiert die Ausgabe in eine Datei
Projekt-Typen:
fastapi FastAPI-Projekte (ignoriert .venv, exportiert a3FASTAPI.txt)
vue Vue.js-Projekte (ignoriert node_modules, exportiert a3VUE.txt)
react React-Projekte (ignoriert node_modules, exportiert a3REACT.txt)
nuxt Nuxt-Projekte (ignoriert node_modules, .nuxt, exportiert a3NUXT.txt)
Beispiele:
a3 ./ Zeigt nur die sichtbare Verzeichnisstruktur
a3 ./ -a Zeigt alle Dateien/Ordner inkl. versteckter Dateien
a3 ./ --exc test,temp Schließt 'test' und 'temp' aus
a3 ./ --export baum.txt Exportiert die Struktur in eine Datei
a3 fastapi Struktur für ein FastAPI-Projekt (mit Exports)
EOF
}
# Versions-Funktion
version() {
echo "asciitree Version 1.2"
}
# Verarbeitung für vordefinierte Projekt-Typen
handle_project_type() {
case "$1" in
"fastapi")
exec "$0" ./ --exc .venv --export a3FASTAPI.txt
;;
"vue")
exec "$0" ./ --exc node_modules,dist --export a3VUE.txt
;;
"react")
exec "$0" ./ --exc node_modules,build --export a3REACT.txt
;;
"nuxt")
exec "$0" ./ --exc node_modules,.nuxt,dist --export a3NUXT.txt
;;
*)
return 1
;;
esac
}
# Hauptbaumstruktur-Funktion
asciitree() {
local dir=${1:-.}
local indent=${2:-0}
local show_files=${3:-false}
local max_depth=${4:-9999}
local current_depth=${5:-0}
local exclude_dirs=(${6//,/ })
local export_file=${7:-""}
local last_prefix="└── "
local mid_prefix="├── "
# Abbruch bei max. Tiefe
if [ "$current_depth" -ge "$max_depth" ]; then
return
fi
# ---- portables realpath (ohne zwingendes Symlink-Resolve) ----
_realpath() {
if command -v realpath >/dev/null 2>&1; then
realpath "$1"
elif command -v grealpath >/dev/null 2>&1; then
grealpath "$1"
else
# Fallback: absoluter Pfad via cd+pwd; löst Symlinks nicht zwingend auf
printf '%s/%s\n' "$(cd "$(dirname -- "$1")" 2>/dev/null && pwd)" "$(basename -- "$1")"
fi
}
# ---- Einträge sicher einlesen (ohne Whitespacesplitting) ----
local -a items=()
if [ "$show_files" = true ]; then
# alle Dateien/Ordner inkl. versteckte
while IFS= read -r line; do items+=("$line"); done < <(LC_ALL=C ls -1A "$dir" 2>/dev/null)
else
# nur sichtbare (ohne .dot) – BSD/macOS-Fallback falls -printf fehlt
if command -v gfind >/dev/null 2>&1; then
while IFS= read -r line; do items+=("$line"); done < <(LC_ALL=C gfind "$dir" -mindepth 1 -maxdepth 1 -not -name ".*" -printf '%f\n' 2>/dev/null)
else
while IFS= read -r line; do items+=("$line"); done < <(LC_ALL=C ls -1 "$dir" 2>/dev/null | grep -v '^\.' || true)
fi
fi
local count=${#items[@]}
local i=1
for item in "${items[@]}"; do
local item_path="$dir/$item"
local abs_item_path="$(_realpath "$item_path" 2>/dev/null)"
# Ausschlüsse prüfen (Name oder absoluter Pfad)
for excluded in "${exclude_dirs[@]}"; do
local abs_excluded="$(_realpath "$excluded" 2>/dev/null || echo "$excluded")"
if [[ "$item" == "$excluded" || "$abs_item_path" == "$abs_excluded" ]]; then
continue 2
fi
done
# Linien zeichnen
local prefix
prefix="$(printf "%${indent}s")"
local output_line
if [ $i -eq $count ]; then
output_line="${prefix}${last_prefix}${item}"
else
output_line="${prefix}${mid_prefix}${item}"
fi
# Ausgabe / Export
if [ -n "$export_file" ]; then
echo "$output_line" >> "$export_file"
else
echo "$output_line"
fi
# Rekursion bei Verzeichnis
if [ -d "$item_path" ]; then
asciitree "$item_path" $((indent + 4)) "$show_files" "$max_depth" $((current_depth + 1)) "${exclude_dirs[*]}" "$export_file"
fi
i=$((i + 1))
done
}
# ----------------- Argumente & Routing -----------------
# Wenn erstes Argument kein Schalter ist, nur echte Projekt-Typen speziell behandeln;
# alles andere als Verzeichnis interpretieren.
dir=""
if [ $# -ge 1 ] && [[ "$1" != -* ]]; then
case "$1" in
fastapi|vue|react|nuxt)
handle_project_type "$1"
exit $? # exec im Handler beendet das Skript in der Regel
;;
*)
dir="$1" # z. B. "./" oder "/path/to/dir"
shift # restliche Optionen (-a, --exc, ...) weiter verarbeiten
;;
esac
fi
# Ohne Argumente → Hilfe
if [ $# -eq 0 ] && [ -z "$dir" ]; then
usage
exit 0
fi
# Variablen
max_depth=9999
show_files=false
exclude_dirs=()
export_file=""
# Optionen parsen
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
-v|--version)
version
exit 0
;;
-a|--all)
show_files=true
shift
;;
-[0-9])
max_depth=${1:1}
shift
;;
--exc)
if [ -n "${2:-}" ]; then
# Kommagetrennte Liste in Array
IFS=',' read -r -a _tmp <<< "$2"
exclude_dirs+=("${_tmp[@]}")
shift 2
else
echo "❌ Fehler: '--exc' benötigt eine Liste von Ordnern."
exit 1
fi
;;
--export)
if [ -n "${2:-}" ]; then
export_file="$2"
: > "$export_file"
shift 2
else
echo "❌ Fehler: '--export' benötigt einen Dateinamen."
exit 1
fi
;;
*)
# weiteres Verzeichnisargument (falls gegeben)
dir="$1"
shift
;;
esac
done
# Standardverzeichnis
if [ -z "$dir" ]; then
dir="."
fi
# Gültigkeit prüfen
if [ ! -d "$dir" ]; then
echo "❌ Fehler: '$dir' ist kein Verzeichnis."
exit 1
fi
# Hauptfunktion aufrufen
asciitree "$dir" 0 "$show_files" "$max_depth" 0 "${exclude_dirs[*]}" "$export_file"
# Abschlussmeldung für Export
if [ -n "$export_file" ]; then
echo "🎉 Struktur wurde erfolgreich in '$export_file' exportiert."
fi