zsh script that takes a variable number of arguments
Clash Royale CLAN TAG#URR8PPP
up vote
3
down vote
favorite
I have just (belatedly) discovered that I can ssh -t from one machine to another and run a command there.
The thought then took me that I should be able to come up with a script that tailed a log file (from a pair) on a machine by doing something like
ssh -t $1 ssh -t $2 tailf /pathtofile/$3/log.log
and indeed if I put in 1,2 and 3 by hand it works just fine.
My problem is that I may have 1,2 or 3 hosts to jump between to make this work.
How would I do this in zsh? I've done some digging and it looks as though shift may be my friend, but I'm a bit lost.
shell-script ssh zsh
add a comment |Â
up vote
3
down vote
favorite
I have just (belatedly) discovered that I can ssh -t from one machine to another and run a command there.
The thought then took me that I should be able to come up with a script that tailed a log file (from a pair) on a machine by doing something like
ssh -t $1 ssh -t $2 tailf /pathtofile/$3/log.log
and indeed if I put in 1,2 and 3 by hand it works just fine.
My problem is that I may have 1,2 or 3 hosts to jump between to make this work.
How would I do this in zsh? I've done some digging and it looks as though shift may be my friend, but I'm a bit lost.
shell-script ssh zsh
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I have just (belatedly) discovered that I can ssh -t from one machine to another and run a command there.
The thought then took me that I should be able to come up with a script that tailed a log file (from a pair) on a machine by doing something like
ssh -t $1 ssh -t $2 tailf /pathtofile/$3/log.log
and indeed if I put in 1,2 and 3 by hand it works just fine.
My problem is that I may have 1,2 or 3 hosts to jump between to make this work.
How would I do this in zsh? I've done some digging and it looks as though shift may be my friend, but I'm a bit lost.
shell-script ssh zsh
I have just (belatedly) discovered that I can ssh -t from one machine to another and run a command there.
The thought then took me that I should be able to come up with a script that tailed a log file (from a pair) on a machine by doing something like
ssh -t $1 ssh -t $2 tailf /pathtofile/$3/log.log
and indeed if I put in 1,2 and 3 by hand it works just fine.
My problem is that I may have 1,2 or 3 hosts to jump between to make this work.
How would I do this in zsh? I've done some digging and it looks as though shift may be my friend, but I'm a bit lost.
shell-script ssh zsh
shell-script ssh zsh
asked Sep 5 at 12:46
Peter NUnn
1184
1184
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
2
down vote
accepted
Since I'm not really a zsh
user, I will write a sh
solution (zsh
should be able to execute it too).
The general gist is to create a list with one ssh -t hostname
bit for each command line option except for the last one, and then to execute that list as a command.
#!/bin/sh
argn=$#
i=0
for arg do
shift
i=$(( i + 1 ))
if [ "$i" -lt "$argn" ]; then
set -- "$@" ssh -t "$arg"
else
set -- "$@" "/pathtofile/$arg/log.log"
fi
done
command "$@"
Running this as
sh script.sh alpha beta gamma zeta
it would create the list
ssh -t alpha ssh -t beta ssh -t gamma /pathtofile/zeta/log.log
The last command in the script would execute this as a command.
The list is built in $@
, the list of positional parameters, which at the start of the script contains the command line parameters of the script. The loop keeps track of when the last element of that original list is encountered and treats it specially.
The set
command, when used as above, will append to the list, and shift
will remove the first element of the list (the one we are currently processing).
I'm sure this could be made shorter and more elegant with zsh
-specific syntax.
I learned this just yesterday!zsh -c 'set -- alpha beta gamma zeta; print -- "-t "$^@'
â Jeff Schaller
Sep 5 at 13:19
1
@JeffSchaller, except that it would become like"-t $1" "-t $2"...
. Usingo=-t; print -- "$(@)o:^^argv"
would make it"-t" "$1" "-t" "$2"
, but here you want"ssh" "-t" "$1" "ssh" "-t" "$2"
, and actually even ratherssh -t "$1" "ssh -t quoted-$2 "...
â Stéphane Chazelas
Sep 5 at 21:11
Where do you find a reference to the arcane incantations such as "$0" etc for these scripts?
â Peter NUnn
Sep 6 at 22:23
@PeterNUnn I don't think I used$0
in this script. Are you asking where to find more information about thesh
shell? In that case, I tend to read the POSIX standard (specifically the "Shell & Utilities" section).
â Kusalananda
Sep 7 at 5:45
add a comment |Â
up vote
2
down vote
I don't think you can easily get away without a loop:
cmd=()
for i ($argv[1,-2]) cmd+=(ssh -t $i)
$cmd tailf /pathtofile/$argv[-1]/log.log
Stritly speaking, since it's a shell command line that you pass to ssh
, if you wanted to be able to support arbitrary values for those $1
, $2
, you'd need quote those arguments and add an extra level of quoting for each ssh.
Here assuming that the login shell of the user on all the hosts is Bourne-like:
cmd=(tailf /pathtofile/$argv[-1]/log.log)
argv[-1]=()
while (($#argv))
cmd=(ssh -t "$argv[-1]" $(j: :)$(qq)cmd)
argv[-1]=()
That should make it work when called as
that-script host1 host2 'dir with spaces and other nasty characters'
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
Since I'm not really a zsh
user, I will write a sh
solution (zsh
should be able to execute it too).
The general gist is to create a list with one ssh -t hostname
bit for each command line option except for the last one, and then to execute that list as a command.
#!/bin/sh
argn=$#
i=0
for arg do
shift
i=$(( i + 1 ))
if [ "$i" -lt "$argn" ]; then
set -- "$@" ssh -t "$arg"
else
set -- "$@" "/pathtofile/$arg/log.log"
fi
done
command "$@"
Running this as
sh script.sh alpha beta gamma zeta
it would create the list
ssh -t alpha ssh -t beta ssh -t gamma /pathtofile/zeta/log.log
The last command in the script would execute this as a command.
The list is built in $@
, the list of positional parameters, which at the start of the script contains the command line parameters of the script. The loop keeps track of when the last element of that original list is encountered and treats it specially.
The set
command, when used as above, will append to the list, and shift
will remove the first element of the list (the one we are currently processing).
I'm sure this could be made shorter and more elegant with zsh
-specific syntax.
I learned this just yesterday!zsh -c 'set -- alpha beta gamma zeta; print -- "-t "$^@'
â Jeff Schaller
Sep 5 at 13:19
1
@JeffSchaller, except that it would become like"-t $1" "-t $2"...
. Usingo=-t; print -- "$(@)o:^^argv"
would make it"-t" "$1" "-t" "$2"
, but here you want"ssh" "-t" "$1" "ssh" "-t" "$2"
, and actually even ratherssh -t "$1" "ssh -t quoted-$2 "...
â Stéphane Chazelas
Sep 5 at 21:11
Where do you find a reference to the arcane incantations such as "$0" etc for these scripts?
â Peter NUnn
Sep 6 at 22:23
@PeterNUnn I don't think I used$0
in this script. Are you asking where to find more information about thesh
shell? In that case, I tend to read the POSIX standard (specifically the "Shell & Utilities" section).
â Kusalananda
Sep 7 at 5:45
add a comment |Â
up vote
2
down vote
accepted
Since I'm not really a zsh
user, I will write a sh
solution (zsh
should be able to execute it too).
The general gist is to create a list with one ssh -t hostname
bit for each command line option except for the last one, and then to execute that list as a command.
#!/bin/sh
argn=$#
i=0
for arg do
shift
i=$(( i + 1 ))
if [ "$i" -lt "$argn" ]; then
set -- "$@" ssh -t "$arg"
else
set -- "$@" "/pathtofile/$arg/log.log"
fi
done
command "$@"
Running this as
sh script.sh alpha beta gamma zeta
it would create the list
ssh -t alpha ssh -t beta ssh -t gamma /pathtofile/zeta/log.log
The last command in the script would execute this as a command.
The list is built in $@
, the list of positional parameters, which at the start of the script contains the command line parameters of the script. The loop keeps track of when the last element of that original list is encountered and treats it specially.
The set
command, when used as above, will append to the list, and shift
will remove the first element of the list (the one we are currently processing).
I'm sure this could be made shorter and more elegant with zsh
-specific syntax.
I learned this just yesterday!zsh -c 'set -- alpha beta gamma zeta; print -- "-t "$^@'
â Jeff Schaller
Sep 5 at 13:19
1
@JeffSchaller, except that it would become like"-t $1" "-t $2"...
. Usingo=-t; print -- "$(@)o:^^argv"
would make it"-t" "$1" "-t" "$2"
, but here you want"ssh" "-t" "$1" "ssh" "-t" "$2"
, and actually even ratherssh -t "$1" "ssh -t quoted-$2 "...
â Stéphane Chazelas
Sep 5 at 21:11
Where do you find a reference to the arcane incantations such as "$0" etc for these scripts?
â Peter NUnn
Sep 6 at 22:23
@PeterNUnn I don't think I used$0
in this script. Are you asking where to find more information about thesh
shell? In that case, I tend to read the POSIX standard (specifically the "Shell & Utilities" section).
â Kusalananda
Sep 7 at 5:45
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
Since I'm not really a zsh
user, I will write a sh
solution (zsh
should be able to execute it too).
The general gist is to create a list with one ssh -t hostname
bit for each command line option except for the last one, and then to execute that list as a command.
#!/bin/sh
argn=$#
i=0
for arg do
shift
i=$(( i + 1 ))
if [ "$i" -lt "$argn" ]; then
set -- "$@" ssh -t "$arg"
else
set -- "$@" "/pathtofile/$arg/log.log"
fi
done
command "$@"
Running this as
sh script.sh alpha beta gamma zeta
it would create the list
ssh -t alpha ssh -t beta ssh -t gamma /pathtofile/zeta/log.log
The last command in the script would execute this as a command.
The list is built in $@
, the list of positional parameters, which at the start of the script contains the command line parameters of the script. The loop keeps track of when the last element of that original list is encountered and treats it specially.
The set
command, when used as above, will append to the list, and shift
will remove the first element of the list (the one we are currently processing).
I'm sure this could be made shorter and more elegant with zsh
-specific syntax.
Since I'm not really a zsh
user, I will write a sh
solution (zsh
should be able to execute it too).
The general gist is to create a list with one ssh -t hostname
bit for each command line option except for the last one, and then to execute that list as a command.
#!/bin/sh
argn=$#
i=0
for arg do
shift
i=$(( i + 1 ))
if [ "$i" -lt "$argn" ]; then
set -- "$@" ssh -t "$arg"
else
set -- "$@" "/pathtofile/$arg/log.log"
fi
done
command "$@"
Running this as
sh script.sh alpha beta gamma zeta
it would create the list
ssh -t alpha ssh -t beta ssh -t gamma /pathtofile/zeta/log.log
The last command in the script would execute this as a command.
The list is built in $@
, the list of positional parameters, which at the start of the script contains the command line parameters of the script. The loop keeps track of when the last element of that original list is encountered and treats it specially.
The set
command, when used as above, will append to the list, and shift
will remove the first element of the list (the one we are currently processing).
I'm sure this could be made shorter and more elegant with zsh
-specific syntax.
edited Sep 5 at 13:23
answered Sep 5 at 13:09
Kusalananda
107k14209331
107k14209331
I learned this just yesterday!zsh -c 'set -- alpha beta gamma zeta; print -- "-t "$^@'
â Jeff Schaller
Sep 5 at 13:19
1
@JeffSchaller, except that it would become like"-t $1" "-t $2"...
. Usingo=-t; print -- "$(@)o:^^argv"
would make it"-t" "$1" "-t" "$2"
, but here you want"ssh" "-t" "$1" "ssh" "-t" "$2"
, and actually even ratherssh -t "$1" "ssh -t quoted-$2 "...
â Stéphane Chazelas
Sep 5 at 21:11
Where do you find a reference to the arcane incantations such as "$0" etc for these scripts?
â Peter NUnn
Sep 6 at 22:23
@PeterNUnn I don't think I used$0
in this script. Are you asking where to find more information about thesh
shell? In that case, I tend to read the POSIX standard (specifically the "Shell & Utilities" section).
â Kusalananda
Sep 7 at 5:45
add a comment |Â
I learned this just yesterday!zsh -c 'set -- alpha beta gamma zeta; print -- "-t "$^@'
â Jeff Schaller
Sep 5 at 13:19
1
@JeffSchaller, except that it would become like"-t $1" "-t $2"...
. Usingo=-t; print -- "$(@)o:^^argv"
would make it"-t" "$1" "-t" "$2"
, but here you want"ssh" "-t" "$1" "ssh" "-t" "$2"
, and actually even ratherssh -t "$1" "ssh -t quoted-$2 "...
â Stéphane Chazelas
Sep 5 at 21:11
Where do you find a reference to the arcane incantations such as "$0" etc for these scripts?
â Peter NUnn
Sep 6 at 22:23
@PeterNUnn I don't think I used$0
in this script. Are you asking where to find more information about thesh
shell? In that case, I tend to read the POSIX standard (specifically the "Shell & Utilities" section).
â Kusalananda
Sep 7 at 5:45
I learned this just yesterday!
zsh -c 'set -- alpha beta gamma zeta; print -- "-t "$^@'
â Jeff Schaller
Sep 5 at 13:19
I learned this just yesterday!
zsh -c 'set -- alpha beta gamma zeta; print -- "-t "$^@'
â Jeff Schaller
Sep 5 at 13:19
1
1
@JeffSchaller, except that it would become like
"-t $1" "-t $2"...
. Using o=-t; print -- "$(@)o:^^argv"
would make it "-t" "$1" "-t" "$2"
, but here you want "ssh" "-t" "$1" "ssh" "-t" "$2"
, and actually even rather ssh -t "$1" "ssh -t quoted-$2 "...
â Stéphane Chazelas
Sep 5 at 21:11
@JeffSchaller, except that it would become like
"-t $1" "-t $2"...
. Using o=-t; print -- "$(@)o:^^argv"
would make it "-t" "$1" "-t" "$2"
, but here you want "ssh" "-t" "$1" "ssh" "-t" "$2"
, and actually even rather ssh -t "$1" "ssh -t quoted-$2 "...
â Stéphane Chazelas
Sep 5 at 21:11
Where do you find a reference to the arcane incantations such as "$0" etc for these scripts?
â Peter NUnn
Sep 6 at 22:23
Where do you find a reference to the arcane incantations such as "$0" etc for these scripts?
â Peter NUnn
Sep 6 at 22:23
@PeterNUnn I don't think I used
$0
in this script. Are you asking where to find more information about the sh
shell? In that case, I tend to read the POSIX standard (specifically the "Shell & Utilities" section).â Kusalananda
Sep 7 at 5:45
@PeterNUnn I don't think I used
$0
in this script. Are you asking where to find more information about the sh
shell? In that case, I tend to read the POSIX standard (specifically the "Shell & Utilities" section).â Kusalananda
Sep 7 at 5:45
add a comment |Â
up vote
2
down vote
I don't think you can easily get away without a loop:
cmd=()
for i ($argv[1,-2]) cmd+=(ssh -t $i)
$cmd tailf /pathtofile/$argv[-1]/log.log
Stritly speaking, since it's a shell command line that you pass to ssh
, if you wanted to be able to support arbitrary values for those $1
, $2
, you'd need quote those arguments and add an extra level of quoting for each ssh.
Here assuming that the login shell of the user on all the hosts is Bourne-like:
cmd=(tailf /pathtofile/$argv[-1]/log.log)
argv[-1]=()
while (($#argv))
cmd=(ssh -t "$argv[-1]" $(j: :)$(qq)cmd)
argv[-1]=()
That should make it work when called as
that-script host1 host2 'dir with spaces and other nasty characters'
add a comment |Â
up vote
2
down vote
I don't think you can easily get away without a loop:
cmd=()
for i ($argv[1,-2]) cmd+=(ssh -t $i)
$cmd tailf /pathtofile/$argv[-1]/log.log
Stritly speaking, since it's a shell command line that you pass to ssh
, if you wanted to be able to support arbitrary values for those $1
, $2
, you'd need quote those arguments and add an extra level of quoting for each ssh.
Here assuming that the login shell of the user on all the hosts is Bourne-like:
cmd=(tailf /pathtofile/$argv[-1]/log.log)
argv[-1]=()
while (($#argv))
cmd=(ssh -t "$argv[-1]" $(j: :)$(qq)cmd)
argv[-1]=()
That should make it work when called as
that-script host1 host2 'dir with spaces and other nasty characters'
add a comment |Â
up vote
2
down vote
up vote
2
down vote
I don't think you can easily get away without a loop:
cmd=()
for i ($argv[1,-2]) cmd+=(ssh -t $i)
$cmd tailf /pathtofile/$argv[-1]/log.log
Stritly speaking, since it's a shell command line that you pass to ssh
, if you wanted to be able to support arbitrary values for those $1
, $2
, you'd need quote those arguments and add an extra level of quoting for each ssh.
Here assuming that the login shell of the user on all the hosts is Bourne-like:
cmd=(tailf /pathtofile/$argv[-1]/log.log)
argv[-1]=()
while (($#argv))
cmd=(ssh -t "$argv[-1]" $(j: :)$(qq)cmd)
argv[-1]=()
That should make it work when called as
that-script host1 host2 'dir with spaces and other nasty characters'
I don't think you can easily get away without a loop:
cmd=()
for i ($argv[1,-2]) cmd+=(ssh -t $i)
$cmd tailf /pathtofile/$argv[-1]/log.log
Stritly speaking, since it's a shell command line that you pass to ssh
, if you wanted to be able to support arbitrary values for those $1
, $2
, you'd need quote those arguments and add an extra level of quoting for each ssh.
Here assuming that the login shell of the user on all the hosts is Bourne-like:
cmd=(tailf /pathtofile/$argv[-1]/log.log)
argv[-1]=()
while (($#argv))
cmd=(ssh -t "$argv[-1]" $(j: :)$(qq)cmd)
argv[-1]=()
That should make it work when called as
that-script host1 host2 'dir with spaces and other nasty characters'
answered Sep 5 at 21:04
Stéphane Chazelas
286k53528866
286k53528866
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f467011%2fzsh-script-that-takes-a-variable-number-of-arguments%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password