-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfield-reveal.sh
191 lines (157 loc) · 5.68 KB
/
field-reveal.sh
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
#!/bin/bash
#--------------------------------------------
# Frederic Gariepy
# https://github.com/FredericGariepy/field-reveal
# Path to the fields.txt file
fields_file="fields.txt"
# TODO
# *change the check to get list from arg2, or other method
# Check if fields_file exists
if [ ! -f "$fields_file" ]; then
echo "Error: $fields_file does not exist."
exit 1
fi
# Check if exactly one argument is passed
# \nfield-reveal -h for help. Would be nice to have this, and more options.
if [ $# -ne 1 ]; then
echo -e "Usage: field-reveal -option /path/to/target. Reveal fields of Directories and Files."
exit 1
fi
# Set the target variable to the argument passed
target="$1"
# Remove the trailing slash if present
target="${target%/}"
# Resolve full path of the target
target=$(realpath "$target" 2>/dev/null)
# Set the LESS environment variable to use a custom prompt
export LESS="--prompt=Press 'q' to quit."
# list directory files with detailed information
list_files() {
# Directory listing
local target="$1"
# Print fields for directories, this is done statically
echo -e "Fields for "$target" : \nIndex, Permissions, Links, Owner, Group, Size, Month, Day, Time, Filename"
{
echo -e "Index, Permissions, Links, Owner, Group, Size, Month, Day, Time, Filename"
# Process the ls output dynamically
ls -al "$target" | tail -n +2 | awk '{
printf "%d\t", NR-1; # Add index
for (i = 1; i <= NF; i++) {
printf "%s\t", $i; # Dynamically handle all fields
}
print ""; # New line after processing a row
}'
} | column -t | less -S -P "Index Permissions Links Owner Group Size Month Day Time Filename | Press 'q' to quit\. -N"
}
# Function to get the target's path relative to significant Linux folders
get_significant_path() {
local target="$1"
# Review: is necessary?
# $? is a special variable. It holds the exit status of the last executed command. 0 if successful.
if [[ $? -ne 0 ]]; then
echo "Error: Path '$1' is not supported."
exit 1
fi
# List of significant folders
local significant_folders=(/etc/ /var/ /usr/ /lib/ /boot/ /opt/ /home/ /proc/ /sys/ /run/)
# Check if $target contains any significant folder
for folder in "${significant_folders[@]}"; do
# Check if the target contains the folder path
if [[ "$target" == *"$folder"* ]]; then
# This keeps the significant folder and everything after it
# remove everything up to and including first occurance of $folder
target="${target#*$folder}"
# prepend the $folder back
target="$folder$target"
targetType=1 # Target is significant
break
fi
done
# return target
echo "$target"
}
# debug print
# target_path=$(get_significant_path "$target")
# echo "$target_path"
show_file() {
local target_path="$1"
local fields_file="$2"
# Get the comma-separated fields for matching target_path from the fields file
local fields=$(awk -F',' -v path="$target_path" '
$1 ~ path { # Does the first field (/path/) being passed to awk match the path in fields_file ?
for (i = 2; i <= NF; i++) { # Process the matching line, skipping over the matching /path/
gsub(/^[ \t]+|[ \t]+$/, "", $i) # Remove leading and trailing spaces/tabs
printf "%s%s", $i, (i < NF ? "," : "") # Print the field followed by a comma
}
}
' "$fields_file")
# Extract separator, awk_parse and fields_count directly from the fields string
separator=$(echo "$fields" | cut -d',' -f1)
separator=${separator:-","}
awk_parser=$(echo "$fields" | cut -d',' -f2)
fields_count=$(echo "$fields" | cut -d',' -f3)
fields=$(echo "$fields" | cut -d',' -f4-)
# If no fields found, exit with error
if [ -z "$fields" ]; then
echo "No fields found for path: $target_path" >&2
return 1
fi
# Print the fields to the terminal
echo -e "Fields for $target_path :\n$fields"
# Prepare header for display
local header=$(printf "%s" "$fields" | tr ',' '\t')
# Pipe the header into less along with the file content
{
# Print header first
echo -e "$header"
# Process the file content
if [ "$awk_parser" == "FPAT" ]; then
tail -n +1 "$target_path" | awk -v FPAT="$separator" -v fields_count="$fields_count" '{
if ($0 ~ /^#/) { next }
if (NF < (fields_count - 1)) { next }
printf "%s", $1
for (i=2; i<=fields_count; i++) {
printf "\t%s", $i
}
for (i=fields_count+1; i<=NF; i++) {
printf " %s", $i
}
printf "\n"
}'
else
tail -n +1 "$target_path" | awk -F "$separator" -v fields_count="$fields_count" '{
if ($0 ~ /^#/) { next }
if (NF < (fields_count - 1)) { next }
printf "%s", $1
for (i=2; i<=fields_count; i++) {
printf "\t%s", $i
}
for (i=fields_count+1; i<=NF; i++) {
printf " %s", $i
}
printf "\n"
}'
fi
} | column -t -s $'\t' | less -S -P "$(echo -e "$header" | tr -s '\t' ', ') | Press 'q' to quit"
}
# Check target type and perform field-reveal
field_reveal() {
if [ -e "$target" ]; then
if [ -d "$target" ]; then
# It's a directory
list_files "$target" # List the files in the folder
return # Exit
fi
if [ -f "$target" ]; then
# It's a file
target_path=$(get_significant_path "$target")
show_file "$target_path" "$fields_file"
return # Exit
fi
exit 1 # Path exists but is neither a file nor a directory (special file)
else
echo "Error: '$target' does not exist."
exit 1 # Path does not exist
fi
}
field_reveal "$target"