Skip to content

Commit 1c672bb

Browse files
committed
merge branch "improve robustness/portability 💪" into dev-2.x :
- use `printf` 💪 instead of `echo` - the `echo` option(e.g. -e -n) may effect correctness, `printf` is more robust 💪 - use `if-else` instead of `&&-||` - about `&&-||` see shell check: https://www.shellcheck.net/wiki/SC2015 - small improvement/refactor
2 parents 84b6218 + 0942d59 commit 1c672bb

File tree

14 files changed

+367
-222
lines changed

14 files changed

+367
-222
lines changed

bin/a2l

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/bash
22
# @Function
3-
# echo each arguments on one line colorfully.
3+
# print each arguments on one line colorfully.
44
#
55
# @Usage
66
# $ ./a2l arg1 arg2
@@ -19,26 +19,22 @@ readonly PROG_VERSION='2.5.0-dev'
1919
# util functions
2020
################################################################################
2121

22-
# NOTE: $'foo' is the escape sequence syntax of bash
23-
readonly ec=$'\033' # escape char
24-
readonly eend=$'\033[0m' # escape end
25-
26-
colorEcho() {
22+
colorPrint() {
2723
local color="$1"
2824
shift
2925
# check isatty in bash https://stackoverflow.com/questions/10022323
3026
# if stdout is console, turn on color output.
31-
[ -t 1 ] && echo "${ec}[1;${color}m$*${eend}" || echo "$*"
32-
}
33-
34-
redEcho() {
35-
colorEcho 31 "$@"
27+
if [ -t 1 ]; then
28+
printf "\033[1;${color}m%s\033[0m\n" "$*"
29+
else
30+
printf '%s\n' "$*"
31+
fi
3632
}
3733

3834
usage() {
3935
cat <<EOF
4036
Usage: ${PROG} [OPTION]... ARG...
41-
echo each arguments on one line colorfully.
37+
print each arguments on one line colorfully.
4238
4339
Example:
4440
${PROG} arg1 arg2
@@ -53,7 +49,7 @@ EOF
5349
}
5450

5551
progVersion() {
56-
echo "$PROG $PROG_VERSION"
52+
printf '%s\n' "$PROG $PROG_VERSION"
5753
exit
5854
}
5955

@@ -94,20 +90,20 @@ readonly args
9490
# biz logic
9591
################################################################################
9692

97-
readonly -a ECHO_COLORS=(33 35 36 31 32 37 34)
93+
readonly -a ROTATE_COLORS=(33 35 36 31 32 37 34)
9894
COUNT=0
99-
rotateColorEcho() {
95+
rotateColorPrint() {
10096
local message="$*"
10197

10298
# skip color for white space
10399
if [[ "$message" =~ ^[[:space:]]*$ ]]; then
104-
echo "$message"
100+
printf '%s\n' "$message"
105101
else
106-
local color="${ECHO_COLORS[COUNT++ % ${#ECHO_COLORS[@]}]}"
107-
colorEcho "$color" "$*"
102+
local color="${ROTATE_COLORS[COUNT++ % ${#ROTATE_COLORS[@]}]}"
103+
colorPrint "$color" "$*"
108104
fi
109105
}
110106

111107
for a in ${args[@]:+"${args[@]}"}; do
112-
rotateColorEcho "$a"
108+
rotateColorPrint "$a"
113109
done

bin/ap

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,24 @@ readonly PROG_VERSION='2.5.0-dev'
2121
# util functions
2222
################################################################################
2323

24-
# NOTE: $'foo' is the escape sequence syntax of bash
25-
readonly ec=$'\033' # escape char
26-
readonly eend=$'\033[0m' # escape end
27-
readonly nl=$'\n' # new line
28-
29-
colorEcho() {
24+
colorPrint() {
3025
local color="$1"
3126
shift
3227
# check isatty in bash https://stackoverflow.com/questions/10022323
3328
# if stdout is console, turn on color output.
34-
[ -t 1 ] && echo "${ec}[1;${color}m$*${eend}" || echo "$*"
29+
if [ -t 1 ]; then
30+
printf "\033[1;${color}m%s\033[0m\n" "$*"
31+
else
32+
printf '%s\n' "$*"
33+
fi
3534
}
3635

37-
redEcho() {
38-
colorEcho 31 "$@"
36+
redPrint() {
37+
colorPrint 31 "$*"
3938
}
4039

4140
die() {
42-
redEcho "Error: $*" 1>&2
41+
redPrint "Error: $*" >&2
4342
exit 1
4443
}
4544

@@ -54,10 +53,15 @@ portableReadLink() {
5453
readlink -f "$file"
5554
;;
5655
Darwin*)
56+
local py_args=(-c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$file")
5757
if command -v greadlink >/dev/null; then
5858
greadlink -f "$file"
59+
elif command -v python3 >/dev/null; then
60+
python3 "${py_args[@]}"
61+
elif command -v python >/dev/null; then
62+
python "${py_args[@]}"
5963
else
60-
python -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$file"
64+
die "fail to find command(greadlink/python3/python) to get absolute path!"
6165
fi
6266
;;
6367
*)
@@ -72,10 +76,12 @@ usage() {
7276
# shellcheck disable=SC2015
7377
[ "$exit_code" != 0 ] && local -r out=/dev/stderr || local -r out=/dev/stdout
7478

75-
(($# > 0)) && redEcho "$*$nl" >$out
79+
# NOTE: $'foo' is the escape sequence syntax of bash
80+
local nl=$'\n' # new line
81+
(($# > 0)) && redPrint "$*$nl" >$out
7682

7783
cat >$out <<EOF
78-
Usage: ${PROG} [OPTION]... ARG...
84+
Usage: ${PROG} [OPTION]... [FILE]...
7985
convert to Absolute Path.
8086
8187
Example:
@@ -91,7 +97,7 @@ EOF
9197
}
9298

9399
progVersion() {
94-
echo "$PROG $PROG_VERSION"
100+
printf '%s\n' "$PROG $PROG_VERSION"
95101
exit
96102
}
97103

@@ -115,7 +121,6 @@ while [ $# -gt 0 ]; do
115121
;;
116122
-*)
117123
usage 2 "${PROG}: unrecognized option '$1'"
118-
break
119124
;;
120125
*)
121126
# if not option, treat all follow files as args
@@ -128,10 +133,20 @@ done
128133
[ ${#files[@]} -eq 0 ] && files=(.)
129134
readonly files
130135

136+
################################################################################
137+
# biz logic
138+
################################################################################
139+
140+
has_error=false
141+
131142
for f in "${files[@]}"; do
132-
! [ -e "$f" ] && {
133-
echo "$f does not exists!"
134-
continue
135-
}
136-
portableReadLink "$f"
143+
if [ -e "$f" ]; then
144+
portableReadLink "$f"
145+
else
146+
redPrint "error: $f does not exists!" >&2
147+
has_error=true
148+
fi
137149
done
150+
151+
# set exit status
152+
! $has_error

bin/c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ readonly PROG_VERSION='2.5.0-dev'
3535
# util functions
3636
################################################################################
3737

38-
readonly ec=$'\033' # escape char
39-
readonly eend=$'\033[0m' # escape end
40-
readonly nl=$'\n' # new line
41-
42-
redEcho() {
43-
[ -t 1 ] && echo "${ec}[1;31m$*$eend" || echo "$*"
38+
printErrorMsg() {
39+
# check isatty in bash https://stackoverflow.com/questions/10022323
40+
# if stdout is console, print with red color.
41+
if [ -t 1 ]; then
42+
printf "\033[1;31m%s\033[0m\n\n" "Error: $*"
43+
else
44+
printf '%s\n\n' "Error: $*"
45+
fi
4446
}
4547

4648
usage() {
@@ -49,7 +51,7 @@ usage() {
4951
# shellcheck disable=SC2015
5052
[ "$exit_code" != 0 ] && local -r out=/dev/stderr || local -r out=/dev/stdout
5153

52-
(($# > 0)) && redEcho "$*$nl" >$out
54+
(($# > 0)) && printErrorMsg "$*" >$out
5355

5456
cat >$out <<EOF
5557
Usage: ${PROG} [OPTION]... [command [command_args ...]]
@@ -73,7 +75,7 @@ EOF
7375
}
7476

7577
progVersion() {
76-
echo "$PROG $PROG_VERSION"
78+
printf '%s\n' "$PROG $PROG_VERSION"
7779
exit
7880
}
7981

@@ -106,7 +108,7 @@ while [ $# -gt 0 ]; do
106108
break
107109
;;
108110
-*)
109-
usage 2 "${PROG}: unrecognized option '$1'"
111+
usage 2 "unrecognized option '$1'"
110112
;;
111113
*)
112114
# if not option, treat all follow args as command

bin/coat

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,22 @@ set -eEuo pipefail
1515
# check isatty in bash https://stackoverflow.com/questions/10022323
1616
[ ! -t 1 ] && exec cat "$@"
1717

18-
# NOTE: $'foo' is the escape sequence syntax of bash
19-
readonly ec=$'\033' # escape char
20-
readonly eend=$'\033[0m' # escape end
21-
22-
readonly -a ECHO_COLORS=(33 35 36 31 32 37 34)
18+
readonly -a ROTATE_COLORS=(33 35 36 31 32 37 34)
2319
COUNT=0
24-
rotateColorEcho() {
20+
rotateColorPrint() {
2521
local message="$*"
2622

2723
# skip color for white space
2824
if [[ "$message" =~ ^[[:space:]]*$ ]]; then
29-
echo "$message"
25+
printf '%s\n' "$message"
3026
else
31-
local color="${ECHO_COLORS[COUNT++ % ${#ECHO_COLORS[@]}]}"
32-
echo "${ec}[1;${color}m$message$eend"
27+
local color="${ROTATE_COLORS[COUNT++ % ${#ROTATE_COLORS[@]}]}"
28+
printf "\033[1;${color}m%s\033[0m\n" "$message"
3329
fi
3430
}
3531

3632
# Bash read line does not read leading spaces
3733
# https://stackoverflow.com/questions/29689172
3834
cat "$@" | while IFS= read -r line; do
39-
rotateColorEcho "$line"
35+
rotateColorPrint "$line"
4036
done

bin/cp-into-docker-run

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,17 @@ readonly PROG_VERSION='2.5.0-dev'
1717
# util functions
1818
################################################################################
1919

20-
# NOTE: $'foo' is the escape sequence syntax of bash
21-
readonly ec=$'\033' # escape char
22-
readonly eend=$'\033[0m' # escape end
23-
readonly nl=$'\n' # new line
24-
25-
redEcho() {
20+
redPrint() {
2621
# -t check: is a terminal device?
27-
[ -t 1 ] && echo "${ec}[1;31m$*$eend" || echo "$*"
22+
if [ -t 1 ]; then
23+
printf "\033[1;31m%s\033[0m\n" "$*"
24+
else
25+
printf '%s\n' "$*"
26+
fi
2827
}
2928

3029
die() {
31-
redEcho "Error: $*" 1>&2
30+
redPrint "Error: $*" 1>&2
3231
exit 1
3332
}
3433

@@ -47,10 +46,15 @@ portableReadLink() {
4746
readlink -f "$file"
4847
;;
4948
Darwin*)
49+
local py_args=(-c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$file")
5050
if command -v greadlink >/dev/null; then
5151
greadlink -f "$file"
52+
elif command -v python3 >/dev/null; then
53+
python3 "${py_args[@]}"
54+
elif command -v python >/dev/null; then
55+
python "${py_args[@]}"
5256
else
53-
python -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$file"
57+
die "fail to find command(greadlink/python3/python) for readlink!"
5458
fi
5559
;;
5660
*)
@@ -65,7 +69,9 @@ usage() {
6569
# shellcheck disable=SC2015
6670
[ "$exit_code" != 0 ] && local -r out=/dev/stderr || local -r out=/dev/stdout
6771

68-
(($# > 0)) && redEcho "$*$nl" >$out
72+
# NOTE: $'foo' is the escape sequence syntax of bash
73+
local nl=$'\n' # new line
74+
(($# > 0)) && redPrint "$*$nl" >$out
6975

7076
cat >$out <<EOF
7177
Usage: ${PROG} [OPTION]... command [command-args]...
@@ -100,7 +106,7 @@ EOF
100106
}
101107

102108
progVersion() {
103-
echo "$PROG $PROG_VERSION"
109+
printf '%s\n' "$PROG $PROG_VERSION"
104110
exit
105111
}
106112

@@ -235,7 +241,7 @@ trap cleanupWhenExit EXIT
235241
########################################
236242

237243
logAndRun() {
238-
$verbose && echo "[$PROG] $*" 1>&2
244+
$verbose && printf '%s\n' "[$PROG] $*" 1>&2
239245
"$@"
240246
}
241247

bin/echo-args

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,37 @@
66
# @author Jerry Lee (oldratlee at gmail dot com)
77
set -eEuo pipefail
88

9-
readonly ec=$'\033' # escape char
10-
readonly eend=$'\033[0m' # escape end
9+
digitCount() {
10+
# argument 1(num) is always a non-negative integer in this script usage,
11+
# so NO argument validation logic.
12+
local num="$1" count=0
13+
while ((num != 0)); do
14+
((++count))
15+
((num = num / 10))
16+
done
17+
echo "$count"
18+
}
19+
20+
digit_count=$(digitCount $#)
21+
readonly arg_count=$# digit_count
22+
23+
readonly red='\033[1;31m'
24+
readonly blue='\033[1;36m'
25+
readonly normal='\033[0m'
1126

12-
echoArg() {
13-
local index="$1" count="$2" value="$3"
27+
printArg() {
28+
local idx="$1" value="$2"
1429

1530
# if stdout is console, turn on color output.
16-
[ -t 1 ] &&
17-
echo "${index}/${count}: ${ec}[1;31m[$eend${ec}[1;36;40m$value$eend${ec}[1;31m]$eend" ||
18-
echo "${index}/${count}: [${value}]"
31+
if [ -t 1 ]; then
32+
printf "%${digit_count}s/%s: ${red}[${blue}%s${red}]${normal}\n" "$idx" "$arg_count" "$value"
33+
else
34+
printf "%${digit_count}s/%s: [%s]\n" "$idx" "$arg_count" "$value"
35+
fi
1936
}
2037

21-
echoArg 0 $# "$0"
38+
printArg 0 "$0"
2239
idx=1
2340
for a; do
24-
echoArg $((idx++)) $# "$a"
41+
printArg $((idx++)) "$a"
2542
done

0 commit comments

Comments
 (0)