-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathtree.sh
More file actions
executable file
·150 lines (138 loc) · 4.79 KB
/
Copy pathtree.sh
File metadata and controls
executable file
·150 lines (138 loc) · 4.79 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
#!/bin/sh
########################################################################
# tree.sh: Display Directory Tree
#
# Description:
# This script displays the directory tree of the specified directory,
# or the current directory if no directory is specified. Hidden directories
# (those starting with a dot) are excluded by default. An option can be
# provided to include these hidden directories in the tree.
#
# Author: id774 (More info: https://id774.net)
# Source Code: https://github.com/id774/scripts
# License: The GPL version 3, or LGPL version 3 (Dual License).
# Contact: idnanashi@gmail.com
#
# Usage:
# ./tree.sh [directory] [-a]
# ./tree.sh [-a] [directory]
#
# Run the script without arguments to display the tree of the current
# directory, with one directory path to display that directory, or with
# '-a' before or after the directory to include hidden entries.
#
# Options:
# -a Include hidden entries.
# -h, --help Display this help information.
# -v, --version Display version information.
#
# Version History:
# v2.1 2026-09-12
# Accept -a before or after the directory and reject extra arguments.
# v2.0 2026-08-22
# Use POSIX find negation when excluding hidden paths.
# v1.9 2026-07-11
# Replace the awk {n,} interval expression in usage() with a portable
# equivalent, since mawk on some systems matches it incorrectly.
# v1.8 2025-06-23
# Unified usage output to display full script header and support common help/version options.
# v1.7 2025-04-13
# Unify log level formatting using [INFO], [WARN], and [ERROR] tags.
# v1.6 2025-03-22
# Unify usage information by extracting help text from header comments.
# v1.5 2025-03-17
# Encapsulated all logic in functions and introduced main function.
# v1.4 2025-03-13
# Redirected error messages to stderr for better logging and debugging.
# v1.3 2024-01-07
# Added an option to include hidden directories in the tree display. Updated command existence and
# execution permission checks using a common function for enhanced reliability and maintainability.
# v1.2 2024-01-04
# Added functionality to accept a directory as an argument. If no argument is provided, the script
# displays the tree of the current directory. Added error handling for non-existent directories.
# v1.1 2023-12-23
# Refactored for POSIX compliance. Replaced Bash-specific syntax with POSIX standard commands
# and structures. Enhanced portability and compatibility across different UNIX-like systems.
# v1.0 2014-10-22
# Initial release.
#
########################################################################
# Display full script header information extracted from the top comment block
usage() {
check_commands awk
awk '
BEGIN { in_header = 0 }
/^#+$/ && length($0) >= 10 { if (!in_header) { in_header = 1; next } else exit }
in_header && /^# ?/ { print substr($0, 3) }
' "$0"
exit 0
}
# Check if required commands exist
check_commands() {
for cmd in "$@"; do
cmd_path=$(command -v "$cmd" 2>/dev/null)
if [ -z "$cmd_path" ]; then
echo "[ERROR] Command '$cmd' is not installed. Please install $cmd and try again." >&2
exit 127
elif [ ! -x "$cmd_path" ]; then
echo "[ERROR] Command '$cmd' is not executable. Please check the permissions." >&2
exit 126
fi
done
}
# Determine the directory and option for hidden files
parse_arguments() {
show_hidden=false
directory=""
directory_set=false
while [ "$#" -gt 0 ]; do
case "$1" in
-a)
show_hidden=true
;;
-h|--help|-v|--version)
usage
;;
-*)
usage
;;
*)
if [ "$directory_set" = true ]; then
usage
fi
directory="$1"
directory_set=true
;;
esac
shift
done
if [ "$directory_set" = false ]; then
directory="."
fi
if [ ! -d "$directory" ]; then
echo "[ERROR] Directory '$directory' does not exist." >&2
exit 1
fi
}
# Display the directory tree
display_tree() {
echo "$directory"
cd "$directory" || exit 1
if [ "$show_hidden" = true ]; then
find . -print | sort | sed '1d;s/^\.//;s/\/\([^/]*\)$/|--\1/;s/\/[^/|]*/| /g'
else
find . ! -path '*/\.*' -print | sort | sed '1d;s/^\.//;s/\/\([^/]*\)$/|--\1/;s/\/[^/|]*/| /g'
fi
}
# Main entry point of the script
main() {
case "$1" in
-h|--help|-v|--version) usage ;;
esac
check_commands find sort sed
parse_arguments "$@"
display_tree
return 0
}
# Execute main function
main "$@"