-
Notifications
You must be signed in to change notification settings - Fork 13
/
netpath
executable file
·120 lines (111 loc) · 3.18 KB
/
netpath
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
#!/usr/bin/env bash
# netpath -- expand local paths to NFS paths
#
# Default mode:
# Arguments are assumed to be local paths; will be expanded to absolute
# paths, prefixed with "/net/<localhost>" and output to stdout.
#
# Command mode aka 'which' mode (-w):
# Arguments are assumed to be command names; will be looked up in $PATH,
# prefixed with "/net/<localhost>" and output to stdout.
#
# Execute mode (-x):
# Arguments are assumed to be a command line; path-like arguments (i.e.
# absolute "/foo" or dot-relative "./foo", but not any others) will be
# expanded to absolute paths, prefixed with "/net/<localhost>", and the
# resulting command executed.
#
# Example:
#
# Run a remote editor on a local file:
#
# $ ssh -t foobox vim $(netpath foo.c)
# $ netpath -x ssh -t foobox vim ./foo.c
#
# (This is similar in effect to `on foobox vim foo.c`, except without
# changing the editor's "working directory" into NFS.)
#
# Execute a local program on a remote system:
#
# $ ssh foobox $(netpath -w frob)
# $ ssh foobox $(netpath ~/bin/frob)
. lib.bash || exit
progname_prefix=1
usage() {
echo "Usage: $progname <path...>"
echo " $progname -w <command...>"
echo " $progname -x <command> [<args>]"
echo ""
echo "In default mode, convert local paths to their /net NFS equivalents."
echo "With -w specified, look up arguments in PATH before converting."
echo ""
echo "In -x mode, execute a command after converting all path-looking"
echo "arguments. This is generally only useful for running 'ssh' or similar"
echo "commands that would make a remote host refer back to local paths."
echo ""
echo_opt "-H <host>" "use a different hostname instead of local host"
echo_opt "-w" "perform PATH lookup for each arg"
echo_opt "-x" "execute a command with expanded paths"
echo_opt "-n" "dry-run (only for '-x')"
}
host=$HOSTNAME
n_flag=0
w_flag=0
x_flag=0
while getopts ":H:nwx" OPT; do
case $OPT in
H) host=$OPTARG;;
n) n_flag=1;;
w) w_flag=1;;
x) x_flag=1;;
*) lib:die_getopts;;
esac
done; shift $((OPTIND-1))
if (( w_flag + x_flag > 1 )); then
vdie "-w and -x modes are mutually exclusive"
fi
if (( n_flag && !x_flag )); then
warn "-n has no effect in modes other than -x"
fi
if (( ! $# )); then
vdie "no arguments specified"
fi
args=()
for iarg; do
if (( w_flag )); then
arg=$(command -v "$iarg") || vdie "'$iarg' not found in PATH"
elif (( x_flag )); then
if [[ $iarg == @(.|./*) ]]; then
arg=$(realpath -s "$iarg")
else
arg=$iarg
fi
else
arg=$(realpath -s "$iarg")
fi
if [[ -L "$arg" ]]; then
# Pre-expand absolute symlink targets as otherwise they would
# point to the client's local path, making the /net indirection
# moot.
target=$(readlink "$arg")
if [[ $target == /* && $target != /@(afs|n|net)/* ]]; then
arg=$target
fi
fi
if [[ $arg == /n/*/* ]]; then
nhost=${arg#/n/}; nhost=${nhost%%/*}
arg="/net/$nhost$HOME/${arg#/n/*/}"
elif [[ $arg == /* && $arg != /@(afs|n|net)/* ]]; then
arg="/net/$host$arg"
fi
args+=("$arg")
done
if (( x_flag )); then
if (( n_flag )); then
echo "${args[@]@Q}"
else
(PS4="+ "; set -x; "${args[@]}")
fi
else
printf '%s\n' "${args[@]}"
fi