Using <<< throws error on sh shell not in bash - bash

In Sh
[SunOs] /opt # sh
[\h] \w \$ read -a array <<< "1 2 3";echo ${array[1]}
syntax error: `<' unexpected
In Bash
[SunOs] ~ # bash
[SunOs] ~ # read -a array <<< "1 2 3";echo ${array[1]}
2
Why the Error thorwn in "sh" shell, i'm using SunOS 5.10 Generic_147440-10 sun4v sparc sun4v

Herestrings aren't supported in sh.
This causes the error when you try to run it using sh.

As a workaround you may use the builtin POSIX command set to assign your arguments to the positional parameters $1, $2, ... or the positional parameter array $# respectively
{
IFS="`printf ' \n\t'`"
export IFS
printf '%s' "$IFS" | od -b
set -- `printf '%s' "1 2 3"`
echo "$0"
echo "$1"
echo "$2"
echo "$3"
echo "$#"
}

Related

Passing arguments between a script and a binary [duplicate]

I am writing a very simple script that calls another script, and I need to propagate the parameters from my current script to the script I am executing.
For instance, my script name is foo.sh and calls bar.sh.
foo.sh:
bar $1 $2 $3 $4
How can I do this without explicitly specifying each parameter?
Use "$#" instead of plain $# if you actually wish your parameters to be passed the same.
Observe:
$ cat no_quotes.sh
#!/bin/bash
echo_args.sh $#
$ cat quotes.sh
#!/bin/bash
echo_args.sh "$#"
$ cat echo_args.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4
$ ./no_quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./no_quotes.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:
$ ./quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./quotes.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:
For bash and other Bourne-like shells:
bar "$#"
Use "$#" (works for all POSIX compatibles).
[...] , bash features the "$#" variable, which expands to all command-line parameters separated by spaces.
From Bash by example.
I realize this has been well answered but here's a comparison between "$#" $# "$*" and $*
Contents of test script:
# cat ./test.sh
#!/usr/bin/env bash
echo "================================="
echo "Quoted DOLLAR-AT"
for ARG in "$#"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-AT"
for ARG in $#; do
echo $ARG
done
echo "================================="
echo "Quoted DOLLAR-STAR"
for ARG in "$*"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-STAR"
for ARG in $*; do
echo $ARG
done
echo "================================="
Now, run the test script with various arguments:
# ./test.sh "arg with space one" "arg2" arg3
=================================
Quoted DOLLAR-AT
arg with space one
arg2
arg3
=================================
NOT Quoted DOLLAR-AT
arg
with
space
one
arg2
arg3
=================================
Quoted DOLLAR-STAR
arg with space one arg2 arg3
=================================
NOT Quoted DOLLAR-STAR
arg
with
space
one
arg2
arg3
=================================
A lot answers here recommends $# or $* with and without quotes, however none seems to explain what these really do and why you should that way. So let me steal this excellent summary from this answer:
+--------+---------------------------+
| Syntax | Effective result |
+--------+---------------------------+
| $* | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| $# | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| "$*" | "$1c$2c$3c...c${N}" |
+--------+---------------------------+
| "$#" | "$1" "$2" "$3" ... "${N}" |
+--------+---------------------------+
Notice that quotes makes all the difference and without them both have identical behavior.
For my purpose, I needed to pass parameters from one script to another as-is and for that the best option is:
# file: parent.sh
# we have some params passed to parent.sh
# which we will like to pass on to child.sh as-is
./child.sh $*
Notice no quotes and $# should work as well in above situation.
#!/usr/bin/env bash
while [ "$1" != "" ]; do
echo "Received: ${1}" && shift;
done;
Just thought this may be a bit more useful when trying to test how args come into your script
If you include $# in a quoted string with other characters the behavior is very odd when there are multiple arguments, only the first argument is included inside the quotes.
Example:
#!/bin/bash
set -x
bash -c "true foo $#"
Yields:
$ bash test.sh bar baz
+ bash -c 'true foo bar' baz
But assigning to a different variable first:
#!/bin/bash
set -x
args="$#"
bash -c "true foo $args"
Yields:
$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'
My SUN Unix has a lot of limitations, even "$#" was not interpreted as desired. My workaround is ${#}. For example,
#!/bin/ksh
find ./ -type f | xargs grep "${#}"
By the way, I had to have this particular script because my Unix also does not support grep -r
Sometimes you want to pass all your arguments, but preceded by a flag (e.g. --flag)
$ bar --flag "$1" --flag "$2" --flag "$3"
You can do this in the following way:
$ bar $(printf -- ' --flag "%s"' "$#")
note: to avoid extra field splitting, you must quote %s and $#, and to avoid having a single string, you cannot quote the subshell of printf.
bar "$#" will be equivalent to bar "$1" "$2" "$3" "$4"
Notice that the quotation marks are important!
"$#", $#, "$*" or $* will each behave slightly different regarding escaping and concatenation as described in this stackoverflow answer.
One closely related use case is passing all given arguments inside an argument like this:
bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\"".
I use a variation of #kvantour's answer to achieve this:
bash -c "bar $(printf -- '"%s" ' "$#")"
Works fine, except if you have spaces or escaped characters. I don't find the way to capture arguments in this case and send to a ssh inside of script.
This could be useful but is so ugly
_command_opts=$( echo "$#" | awk -F\- 'BEGIN { OFS=" -" } { for (i=2;i<=NF;i++) { gsub(/^[a-z] /,"&#",$i) ; gsub(/ $/,"",$i );gsub (/$/,"#",$i) }; print $0 }' | tr '#' \' )
"${array[#]}" is the right way for passing any array in bash. I want to provide a full cheat sheet: how to prepare arguments, bypass and process them.
pre.sh -> foo.sh -> bar.sh.
#!/bin/bash
args=("--a=b c" "--e=f g")
args+=("--q=w e" "--a=s \"'d'\"")
./foo.sh "${args[#]}"
#!/bin/bash
./bar.sh "$#"
#!/bin/bash
echo $1
echo $2
echo $3
echo $4
result:
--a=b c
--e=f g
--q=w e
--a=s "'d'"

Hide or suppress arguments value passed to a shell script

From a local machine I am running a shell script on a remote server and passing some arguments to the scripts. Like test.sh "name" "age"
This is my script:
#!/bin/bash
echo $1
echo $2
On the remote server while the script is executing and if I run ps aux | grep .sh i could see the value of the two parameters. Like bash -s name age
Is there a way to suppress or hide the values in the running shell process so that one can see the parameters ?
I have an idea. You could create a global environment variable with unique name and save there the positional arguments, then re-exec your process and get the arguments:
#!/bin/bash
if [[ -z "$MYARGS" ]]; then
export MYARGS="$(printf "%q " "$#")"
exec "$0"
fi
eval set -- "$MYARGS"
printf -- "My arguments:\n"
printf -- "-- %s\n" "$#"
sleep infinity
It will hide it from ps aux:
$ ps aux | grep 1.sh
kamil 196704 0.4 0.0 9768 2084 pts/1 S+ 16:49 0:00 /bin/bash /tmp/1.sh
kamil 196777 0.0 0.0 8924 1640 pts/2 S+ 16:49 0:00 grep 1.sh
The environment variable could be still extracted from /proc:
$ cat /proc/196704/environ | sed -z '/MYARGS/!d'; echo
MYARGS=1 2 3 54 5
Another way might be writing the positional arguments as a string on stdin and pass it to outselves with original input:
#!/bin/bash
if [[ -z "$MYARGS" ]]; then
export MYARGS=1 # just so it's set
# restart outselves with no arguments
exec "$0" < <(
# Stream arguments on stdin on one line
printf "%q " "$#" | xxd -p | tr -d '\n'
echo
exec cat
)
fi
IFS= read -r args # read _one line_ of input - it's our arguments
args=$(xxd -r -p <<<"$args") # encoded with xxd
eval set -- "$args"
printf -- "My arguments:\n"
printf -- "-- %s\n" "$#"
sleep infinity
Here's a way to take the cmd line args and read args from stdin:
#!/usr/bin/env bash
args=()
for arg; do
printf "%d\t%s\n" $((++c)) "$arg"
args+=("$arg")
done
if ! [[ -t 0 ]]; then
while IFS= read -r arg; do
args+=("$arg")
done
fi
declare -p args
Do you can do:
script.sh hello world
printf "%s\n" hello world | script.sh
echo world | script.sh hello

Take file as an input and run awk command on it [duplicate]

I am writing a very simple script that calls another script, and I need to propagate the parameters from my current script to the script I am executing.
For instance, my script name is foo.sh and calls bar.sh.
foo.sh:
bar $1 $2 $3 $4
How can I do this without explicitly specifying each parameter?
Use "$#" instead of plain $# if you actually wish your parameters to be passed the same.
Observe:
$ cat no_quotes.sh
#!/bin/bash
echo_args.sh $#
$ cat quotes.sh
#!/bin/bash
echo_args.sh "$#"
$ cat echo_args.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4
$ ./no_quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./no_quotes.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:
$ ./quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./quotes.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:
For bash and other Bourne-like shells:
bar "$#"
Use "$#" (works for all POSIX compatibles).
[...] , bash features the "$#" variable, which expands to all command-line parameters separated by spaces.
From Bash by example.
I realize this has been well answered but here's a comparison between "$#" $# "$*" and $*
Contents of test script:
# cat ./test.sh
#!/usr/bin/env bash
echo "================================="
echo "Quoted DOLLAR-AT"
for ARG in "$#"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-AT"
for ARG in $#; do
echo $ARG
done
echo "================================="
echo "Quoted DOLLAR-STAR"
for ARG in "$*"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-STAR"
for ARG in $*; do
echo $ARG
done
echo "================================="
Now, run the test script with various arguments:
# ./test.sh "arg with space one" "arg2" arg3
=================================
Quoted DOLLAR-AT
arg with space one
arg2
arg3
=================================
NOT Quoted DOLLAR-AT
arg
with
space
one
arg2
arg3
=================================
Quoted DOLLAR-STAR
arg with space one arg2 arg3
=================================
NOT Quoted DOLLAR-STAR
arg
with
space
one
arg2
arg3
=================================
A lot answers here recommends $# or $* with and without quotes, however none seems to explain what these really do and why you should that way. So let me steal this excellent summary from this answer:
+--------+---------------------------+
| Syntax | Effective result |
+--------+---------------------------+
| $* | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| $# | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| "$*" | "$1c$2c$3c...c${N}" |
+--------+---------------------------+
| "$#" | "$1" "$2" "$3" ... "${N}" |
+--------+---------------------------+
Notice that quotes makes all the difference and without them both have identical behavior.
For my purpose, I needed to pass parameters from one script to another as-is and for that the best option is:
# file: parent.sh
# we have some params passed to parent.sh
# which we will like to pass on to child.sh as-is
./child.sh $*
Notice no quotes and $# should work as well in above situation.
#!/usr/bin/env bash
while [ "$1" != "" ]; do
echo "Received: ${1}" && shift;
done;
Just thought this may be a bit more useful when trying to test how args come into your script
If you include $# in a quoted string with other characters the behavior is very odd when there are multiple arguments, only the first argument is included inside the quotes.
Example:
#!/bin/bash
set -x
bash -c "true foo $#"
Yields:
$ bash test.sh bar baz
+ bash -c 'true foo bar' baz
But assigning to a different variable first:
#!/bin/bash
set -x
args="$#"
bash -c "true foo $args"
Yields:
$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'
My SUN Unix has a lot of limitations, even "$#" was not interpreted as desired. My workaround is ${#}. For example,
#!/bin/ksh
find ./ -type f | xargs grep "${#}"
By the way, I had to have this particular script because my Unix also does not support grep -r
Sometimes you want to pass all your arguments, but preceded by a flag (e.g. --flag)
$ bar --flag "$1" --flag "$2" --flag "$3"
You can do this in the following way:
$ bar $(printf -- ' --flag "%s"' "$#")
note: to avoid extra field splitting, you must quote %s and $#, and to avoid having a single string, you cannot quote the subshell of printf.
bar "$#" will be equivalent to bar "$1" "$2" "$3" "$4"
Notice that the quotation marks are important!
"$#", $#, "$*" or $* will each behave slightly different regarding escaping and concatenation as described in this stackoverflow answer.
One closely related use case is passing all given arguments inside an argument like this:
bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\"".
I use a variation of #kvantour's answer to achieve this:
bash -c "bar $(printf -- '"%s" ' "$#")"
Works fine, except if you have spaces or escaped characters. I don't find the way to capture arguments in this case and send to a ssh inside of script.
This could be useful but is so ugly
_command_opts=$( echo "$#" | awk -F\- 'BEGIN { OFS=" -" } { for (i=2;i<=NF;i++) { gsub(/^[a-z] /,"&#",$i) ; gsub(/ $/,"",$i );gsub (/$/,"#",$i) }; print $0 }' | tr '#' \' )
"${array[#]}" is the right way for passing any array in bash. I want to provide a full cheat sheet: how to prepare arguments, bypass and process them.
pre.sh -> foo.sh -> bar.sh.
#!/bin/bash
args=("--a=b c" "--e=f g")
args+=("--q=w e" "--a=s \"'d'\"")
./foo.sh "${args[#]}"
#!/bin/bash
./bar.sh "$#"
#!/bin/bash
echo $1
echo $2
echo $3
echo $4
result:
--a=b c
--e=f g
--q=w e
--a=s "'d'"

Propagate all arguments in a Bash shell script

I am writing a very simple script that calls another script, and I need to propagate the parameters from my current script to the script I am executing.
For instance, my script name is foo.sh and calls bar.sh.
foo.sh:
bar $1 $2 $3 $4
How can I do this without explicitly specifying each parameter?
Use "$#" instead of plain $# if you actually wish your parameters to be passed the same.
Observe:
$ cat no_quotes.sh
#!/bin/bash
echo_args.sh $#
$ cat quotes.sh
#!/bin/bash
echo_args.sh "$#"
$ cat echo_args.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4
$ ./no_quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./no_quotes.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:
$ ./quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./quotes.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:
For bash and other Bourne-like shells:
bar "$#"
Use "$#" (works for all POSIX compatibles).
[...] , bash features the "$#" variable, which expands to all command-line parameters separated by spaces.
From Bash by example.
I realize this has been well answered but here's a comparison between "$#" $# "$*" and $*
Contents of test script:
# cat ./test.sh
#!/usr/bin/env bash
echo "================================="
echo "Quoted DOLLAR-AT"
for ARG in "$#"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-AT"
for ARG in $#; do
echo $ARG
done
echo "================================="
echo "Quoted DOLLAR-STAR"
for ARG in "$*"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-STAR"
for ARG in $*; do
echo $ARG
done
echo "================================="
Now, run the test script with various arguments:
# ./test.sh "arg with space one" "arg2" arg3
=================================
Quoted DOLLAR-AT
arg with space one
arg2
arg3
=================================
NOT Quoted DOLLAR-AT
arg
with
space
one
arg2
arg3
=================================
Quoted DOLLAR-STAR
arg with space one arg2 arg3
=================================
NOT Quoted DOLLAR-STAR
arg
with
space
one
arg2
arg3
=================================
A lot answers here recommends $# or $* with and without quotes, however none seems to explain what these really do and why you should that way. So let me steal this excellent summary from this answer:
+--------+---------------------------+
| Syntax | Effective result |
+--------+---------------------------+
| $* | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| $# | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| "$*" | "$1c$2c$3c...c${N}" |
+--------+---------------------------+
| "$#" | "$1" "$2" "$3" ... "${N}" |
+--------+---------------------------+
Notice that quotes makes all the difference and without them both have identical behavior.
For my purpose, I needed to pass parameters from one script to another as-is and for that the best option is:
# file: parent.sh
# we have some params passed to parent.sh
# which we will like to pass on to child.sh as-is
./child.sh $*
Notice no quotes and $# should work as well in above situation.
#!/usr/bin/env bash
while [ "$1" != "" ]; do
echo "Received: ${1}" && shift;
done;
Just thought this may be a bit more useful when trying to test how args come into your script
If you include $# in a quoted string with other characters the behavior is very odd when there are multiple arguments, only the first argument is included inside the quotes.
Example:
#!/bin/bash
set -x
bash -c "true foo $#"
Yields:
$ bash test.sh bar baz
+ bash -c 'true foo bar' baz
But assigning to a different variable first:
#!/bin/bash
set -x
args="$#"
bash -c "true foo $args"
Yields:
$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'
My SUN Unix has a lot of limitations, even "$#" was not interpreted as desired. My workaround is ${#}. For example,
#!/bin/ksh
find ./ -type f | xargs grep "${#}"
By the way, I had to have this particular script because my Unix also does not support grep -r
Sometimes you want to pass all your arguments, but preceded by a flag (e.g. --flag)
$ bar --flag "$1" --flag "$2" --flag "$3"
You can do this in the following way:
$ bar $(printf -- ' --flag "%s"' "$#")
note: to avoid extra field splitting, you must quote %s and $#, and to avoid having a single string, you cannot quote the subshell of printf.
bar "$#" will be equivalent to bar "$1" "$2" "$3" "$4"
Notice that the quotation marks are important!
"$#", $#, "$*" or $* will each behave slightly different regarding escaping and concatenation as described in this stackoverflow answer.
One closely related use case is passing all given arguments inside an argument like this:
bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\"".
I use a variation of #kvantour's answer to achieve this:
bash -c "bar $(printf -- '"%s" ' "$#")"
Works fine, except if you have spaces or escaped characters. I don't find the way to capture arguments in this case and send to a ssh inside of script.
This could be useful but is so ugly
_command_opts=$( echo "$#" | awk -F\- 'BEGIN { OFS=" -" } { for (i=2;i<=NF;i++) { gsub(/^[a-z] /,"&#",$i) ; gsub(/ $/,"",$i );gsub (/$/,"#",$i) }; print $0 }' | tr '#' \' )
"${array[#]}" is the right way for passing any array in bash. I want to provide a full cheat sheet: how to prepare arguments, bypass and process them.
pre.sh -> foo.sh -> bar.sh.
#!/bin/bash
args=("--a=b c" "--e=f g")
args+=("--q=w e" "--a=s \"'d'\"")
./foo.sh "${args[#]}"
#!/bin/bash
./bar.sh "$#"
#!/bin/bash
echo $1
echo $2
echo $3
echo $4
result:
--a=b c
--e=f g
--q=w e
--a=s "'d'"

Pass ALL Arguments from Bash Script to Another Command [duplicate]

I am writing a very simple script that calls another script, and I need to propagate the parameters from my current script to the script I am executing.
For instance, my script name is foo.sh and calls bar.sh.
foo.sh:
bar $1 $2 $3 $4
How can I do this without explicitly specifying each parameter?
Use "$#" instead of plain $# if you actually wish your parameters to be passed the same.
Observe:
$ cat no_quotes.sh
#!/bin/bash
echo_args.sh $#
$ cat quotes.sh
#!/bin/bash
echo_args.sh "$#"
$ cat echo_args.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4
$ ./no_quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./no_quotes.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:
$ ./quotes.sh first second
Received: first
Received: second
Received:
Received:
$ ./quotes.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:
For bash and other Bourne-like shells:
bar "$#"
Use "$#" (works for all POSIX compatibles).
[...] , bash features the "$#" variable, which expands to all command-line parameters separated by spaces.
From Bash by example.
I realize this has been well answered but here's a comparison between "$#" $# "$*" and $*
Contents of test script:
# cat ./test.sh
#!/usr/bin/env bash
echo "================================="
echo "Quoted DOLLAR-AT"
for ARG in "$#"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-AT"
for ARG in $#; do
echo $ARG
done
echo "================================="
echo "Quoted DOLLAR-STAR"
for ARG in "$*"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-STAR"
for ARG in $*; do
echo $ARG
done
echo "================================="
Now, run the test script with various arguments:
# ./test.sh "arg with space one" "arg2" arg3
=================================
Quoted DOLLAR-AT
arg with space one
arg2
arg3
=================================
NOT Quoted DOLLAR-AT
arg
with
space
one
arg2
arg3
=================================
Quoted DOLLAR-STAR
arg with space one arg2 arg3
=================================
NOT Quoted DOLLAR-STAR
arg
with
space
one
arg2
arg3
=================================
A lot answers here recommends $# or $* with and without quotes, however none seems to explain what these really do and why you should that way. So let me steal this excellent summary from this answer:
+--------+---------------------------+
| Syntax | Effective result |
+--------+---------------------------+
| $* | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| $# | $1 $2 $3 ... ${N} |
+--------+---------------------------+
| "$*" | "$1c$2c$3c...c${N}" |
+--------+---------------------------+
| "$#" | "$1" "$2" "$3" ... "${N}" |
+--------+---------------------------+
Notice that quotes makes all the difference and without them both have identical behavior.
For my purpose, I needed to pass parameters from one script to another as-is and for that the best option is:
# file: parent.sh
# we have some params passed to parent.sh
# which we will like to pass on to child.sh as-is
./child.sh $*
Notice no quotes and $# should work as well in above situation.
#!/usr/bin/env bash
while [ "$1" != "" ]; do
echo "Received: ${1}" && shift;
done;
Just thought this may be a bit more useful when trying to test how args come into your script
If you include $# in a quoted string with other characters the behavior is very odd when there are multiple arguments, only the first argument is included inside the quotes.
Example:
#!/bin/bash
set -x
bash -c "true foo $#"
Yields:
$ bash test.sh bar baz
+ bash -c 'true foo bar' baz
But assigning to a different variable first:
#!/bin/bash
set -x
args="$#"
bash -c "true foo $args"
Yields:
$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'
My SUN Unix has a lot of limitations, even "$#" was not interpreted as desired. My workaround is ${#}. For example,
#!/bin/ksh
find ./ -type f | xargs grep "${#}"
By the way, I had to have this particular script because my Unix also does not support grep -r
Sometimes you want to pass all your arguments, but preceded by a flag (e.g. --flag)
$ bar --flag "$1" --flag "$2" --flag "$3"
You can do this in the following way:
$ bar $(printf -- ' --flag "%s"' "$#")
note: to avoid extra field splitting, you must quote %s and $#, and to avoid having a single string, you cannot quote the subshell of printf.
bar "$#" will be equivalent to bar "$1" "$2" "$3" "$4"
Notice that the quotation marks are important!
"$#", $#, "$*" or $* will each behave slightly different regarding escaping and concatenation as described in this stackoverflow answer.
One closely related use case is passing all given arguments inside an argument like this:
bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\"".
I use a variation of #kvantour's answer to achieve this:
bash -c "bar $(printf -- '"%s" ' "$#")"
Works fine, except if you have spaces or escaped characters. I don't find the way to capture arguments in this case and send to a ssh inside of script.
This could be useful but is so ugly
_command_opts=$( echo "$#" | awk -F\- 'BEGIN { OFS=" -" } { for (i=2;i<=NF;i++) { gsub(/^[a-z] /,"&#",$i) ; gsub(/ $/,"",$i );gsub (/$/,"#",$i) }; print $0 }' | tr '#' \' )
"${array[#]}" is the right way for passing any array in bash. I want to provide a full cheat sheet: how to prepare arguments, bypass and process them.
pre.sh -> foo.sh -> bar.sh.
#!/bin/bash
args=("--a=b c" "--e=f g")
args+=("--q=w e" "--a=s \"'d'\"")
./foo.sh "${args[#]}"
#!/bin/bash
./bar.sh "$#"
#!/bin/bash
echo $1
echo $2
echo $3
echo $4
result:
--a=b c
--e=f g
--q=w e
--a=s "'d'"

Resources