feat(user/triml.sh):Defronts shared filename prefixes
[BK-2020-03.git] / unitproc / palign.sh
CommitLineData
6ad3cfe2
SBS
1#!/bin/bash
2# Desc: Aligns path elements with spaces
3# Usage: palign.sh [path]
4# find . -type f | palign.sh
5# Input: stdin paths newline-delimited paths (forward-slash delimited)
6# psargs paths word-delimited paths (forward-slash delimited)
7# Output: stdout
8# Depends: Bash 5.1.16
9# Version: 0.0.1
10
11yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
12die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status
13must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails
14read_stdin() {
15 # Desc: Consumes stdin; outputs as stdout lines
16 # Input: stdin (consumes)
17 # Output: stdout (newline delimited)
18 # return 0 stdin read
19 # return 1 stdin not present
20 # Example: printf "foo\nbar\n" | read_stdin
21 # Depends: GNU bash (version 5.1.16), GNU Coreutils 8.32 (cat)
22 # Version: 0.1.1
23 # Attrib: Steven Baltakatei Sandoval (2024-01-29). reboil.com
24 local input_stdin output;
25
26 # Store stdin
27 if [[ -p /dev/stdin ]]; then
28 input_stdin="$(cat -)" || {
29 echo "FATAL:Error reading stdin." 1>&2; return 1; };
30 else
31 return 1;
32 fi;
33
34 # Store as output array elements
35 ## Read in stdin
36 if [[ -n $input_stdin ]]; then
37 while read -r line; do
38 output+=("$line");
39 done < <(printf "%s\n" "$input_stdin") || {
40 echo "FATAL:Error parsing stdin."; return 1; };
41 fi;
42
43 # Print to stdout
44 printf "%s\n" "${output[@]}";
45
46 return 0;
47}; # read stdin to stdout lines
48read_psarg() {
49 # Desc: Reads arguments; outputs as stdout lines
50 # Input: args
51 # Output: stdout (newline delimited)
52 # Example: read_psarg "$@"
53 # Depends: GNU bash (version 5.1.16)
54 # Version: 0.0.1
55 local input_psarg output;
56
57 # Store arguments
58 if [[ $# -gt 0 ]]; then
59 input_psarg="$*";
60 fi;
61
62 # Store as output array elements
63 ## Read in positional arguments
64 if [[ -n $input_psarg ]]; then
65 for arg in "$@"; do
66 output+=("$arg");
67 done;
68 fi;
69
70 # Print to stdout
71 printf "%s\n" "${output[@]}";
72}; # read positional argument to stdout lines
73calculate_max_lengths() {
74 # Calculate maximum lengths of each hierarchical level
75 # Input: psargs paths
76 # Output: stdout ints path element lengths (single line of space-separated ints)
77 local -a paths=("$@");
78 local lengths;
79
80 for path in "${paths[@]}"; do
81 IFS='/' read -r -a parts <<< "$path";
82 # Analyze path element lengths
83 for i in "${!parts[@]}"; do
84 # Save max path element lengths for previously analyzed paths
85 # Note: $(( condition ? value_true : value_false ))
86 # condition: ${#parts[$i]} > ${lengths[$i]:-0} is path element longer than previously seen corresponding paths?
87 # value_true: ${#parts[$i]} save new max length
88 # value_false ${lengths[$i]:-0} use previous value (or init with 0 if never seen before)
89 lengths[$i]=$(( ${#parts[$i]} > ${lengths[$i]:-0} ? ${#parts[$i]} : ${lengths[$i]:-0} ));
90 done;
91 done;
92 echo "${lengths[@]}";
93}; # Get maximum lengths of path elements as space-separated ints
94align_paths() {
95 # Align paths
96 # Input: stdin
97 # Output: stdout
98 # Depends: calculate_max_lengths()
99 local -a paths lengths;
100
101 # Read stdin
102 while read -r line; do
103 paths+=("$line");
104 done < <(read_stdin);
105
106 IFS=" " read -r -a lengths <<< "$(calculate_max_lengths "${paths[@]}")";
107
108 for path in "${paths[@]}"; do
109 IFS='/' read -r -a parts <<< "$path";
110 formatted_path="";
111 for i in "${!parts[@]}"; do
112 if [[ $i -gt 0 ]]; then
113 formatted_path+="/";
114 fi;
115 formatted_path+="${parts[$i]}";
116 if [[ $i -lt $((${#parts[@]} - 1)) ]]; then
117 formatted_path+=$(printf "%*s" $((${lengths[$i]} - ${#parts[$i]} + 1)) "");
118 fi;
119 done;
120 echo "$formatted_path";
121 done;
122}; # Function to format and align paths
123main() {
124 { read_stdin; read_psarg "$@"; } | align_paths;
125}; # Call the function with the file paths
126main "$@";
127
128# Author: Steven Baltakatei Sandoval
129# License; GPLv3+