-
Notifications
You must be signed in to change notification settings - Fork 13
/
each
executable file
·112 lines (101 loc) · 2.19 KB
/
each
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
#!/usr/bin/env bash
# each -- apply command to each argument individually
. lib.bash || exit
usage() {
echo "Usage: ${0##*/} [-env] <command> [<static args> --] <loop args>"
echo
echo_opt "-e" "exit if a command fails"
echo_opt "-n" "dry run (output shell commands but don't run them)"
echo_opt "-v" "verbose (show commands before running)"
echo
echo "The static arguments may include a {}, which will be replaced with the current"
echo "loop argument in each iteration; otherwise the argument will be appended to the"
echo "end of the command."
}
Xecho() {
printf '%q ' "${@:1:$#-1}"
printf '%q\n' "${!#}"
}
Xverb() {
echo -n "Running: "; Xecho "$@"; "$@"
}
args=()
cmd=()
dryrun=0
verbose=0
errexit=0
flag=0
while getopts ":env" OPT; do
case $OPT in
e) errexit=1;;
n) dryrun=1;;
v) verbose=1;;
*) lib:die_getopts;;
esac
done; shift $((OPTIND-1))
if [[ -t 0 ]]; then
# Find the *last* double-dash arg
ldash=0
for (( i=1; i<=$#; i++ )); do
if [[ ${!i} == "--" ]]; then
ldash=$i
fi
done
if (( ldash )); then
# Split command args and loop args at the last double-dash
cmd=("${@:1:ldash-1}")
args=("${@:ldash+1}")
else
# For convenience, if no double-dash then assume that only
# the first word is the command, e.g. 'each unzip *.zip'.
cmd=("${@:1:1}")
args=("${@:2}")
fi
else
# Will read loop args from stdin, like 'xargs -i'
cmd=("$@")
fi
if (( ! ${#cmd[@]} )); then
echo "each: command not specified" >&2
exit 2
fi
if (( dryrun )); then
cmd=(Xecho "${cmd[@]}")
elif (( verbose )); then
cmd=(Xverb "${cmd[@]}")
fi
lpos=()
for (( i=0; i<${#cmd[@]}; i++ )); do
if [[ ${cmd[i]} == *"{}"* ]]; then
lpos+=($i)
fi
done
if (( !lpos )); then
lpos=(${#cmd[@]})
cmd+=("{}")
fi
if [[ -t 0 ]]; then
lcmd=("${cmd[@]}")
for arg in "${args[@]}"; do
for i in ${lpos[@]}; do
lcmd[i]=${cmd[i]//"{}"/"$arg"}
done
"${lcmd[@]}"
if (( $? && errexit )); then
echo "each: command failed with result $?" >&2
exit 1
fi
done
else
lcmd=("${cmd[@]}")
while IFS= read -r arg; do
for i in ${lpos[@]}; do
lcmd[i]=${cmd[i]//"{}"/"$arg"}
done
"${lcmd[@]}" </dev/tty
if (( $? && errexit )); then
echo "each: command failed with result $?" >&2
exit 1
fi
done
fi