Na verdade, a resposta de @ Graeme - e sua pergunta - estão apenas referenciando os efeitos colaterais de como o shell lida. "$@positional $*parameters".Estes são atribuídos pelo shell aos seus argumentos na chamada e a qualquer momento depois com o setutilitário interno. Eles podem ser chamados a qualquer momento, com o "$*"qual divide cada posição com o primeiro caractere "$IFS"ou "$@"que cita cada posição e os divide com todos os"$IFS."
man set
NAME
set — set or unset options and positional parameters
SYNOPSIS
set [−abCefhmnuvx] [−o option] [argument...]
set [+abCefhmnuvx] [+o option] [argument...]
set −− [argument...]
set −o
set +o
Se você já possui os valores que está alimentando com a concha, não precisa --três vezes. Os parâmetros do shell são setcapazes - sempre, a qualquer momento, não apenas na chamada (exceto $ 0 e -i):
su - mikeserv -c 'set -- "$*" ; echo "$*" ;
set -- 4 5 6 ; echo "$*"' -- -- 7 8 9
7 8 9
4 5 6
E todas essas citações de shell podem ser confusas. Isso simplifica um pouco as coisas:
( set -- 4 5 6
su - mikeserv 4<<-\CMD /dev/fd/4 "$@"
echo $0 "$*"
set -- "$*"
echo "$*"
set -- 7 8 9
echo "$*"
CMD
)
/dev/fd/4 4 5 6
4 5 6
7 8 9
Os argumentos do shell pai são set4, 5 e 6 e depois são passados para o subshell invocado por sumeio da posiçãoparameter "$@array".
Observe como eu ( subshell )o comando acima - faço isso porque não quero mexer no meu ambiente de shell atual - porque posso inadvertidamente alterar algo que preferiria não fazer se fizesse comset.
SOBRE REDIRECÇÃO:
Primeiro de tudo, seu sistema Unix funciona com arquivos - permissões de arquivos, conteúdo e atributos de arquivos. De uma maneira ou de outra, todos os objetos de dados que você usa podem (e, pelo menos na minha opinião, deveriam) ser endereçados como um arquivo. O redirecionamento aponta para um arquivo - é tudo. A <<HERE-DOCUMENTdescreverá um arquivo em linha e o redirecionará. As expansões de shell são interpretadas ou não.
O autor da pergunta observa nos comentários abaixo que, quando ele tenta usar esse método como rootusuário, ele recebe um erro de permissão. Quando respondi, sugeri que ele chownou chgrpo /dev/fd/${num}arquivo especial, mas esse provavelmente não é o melhor método. A razão pela qual ele encontra esse problema rooté conceder readpermissões, mas não execute permissões. Você pode lidar com isso facilmente, apenas evitando uma execchamada. Em vez de chamar o /dev/fd/${num}arquivo diretamente na linha de comando, faça:
su -c '. /dev/fd/'${num} ${num}<<SCRIPT
O uso de dois heredocs pode ajudar a escapar. Aqui está o que acontece em todos os casos:
NO SET IN <<HEREDOC
sh 3<<\CMD /dev/fd/3
( echo 'without set "$@" or \$@ in here-doc' ; echo
set -- '1 "2" 3' 4 "5 6"
su - mikeserv 4<<-UNQUOTED 5<<-\PREQUOTED /dev/fd/4
echo UNQUOTED; echo $0 "$*"
printf "%s\\t\\t%s\\t\\t%s\\t\\t%s\\n" $(printf "'%s' " "$@") \\
$@ '$@' "$@" '"$@"' "'$@'" \$@ '\$@' "\$@" '"\$@"'
. /dev/fd/5
UNQUOTED
echo PREQUOTED ; echo $0 "$*"
printf "%s\t\t%s\t\t%s\t\t%s\n" $(printf "'%s' " "$@") \
$@ '$@' "$@" '"$@"' \$@ '\$@' "\$@" '"\$@"'
PREQUOTED
)
CMD
RESULTADO
without set "$@" or \$@ in here-doc
UNQUOTED
/dev/fd/3 1 2 3 4 5 6
1 "2" 3 4 5 6 1
2 3 4 5
6 1 "2" 3 4 5 6 1 2 3 4 5 6 "1 "2" 3 4 5 6"
'1 2 3 4 5 6' $@ "$@"
PREQUOTED
/dev/fd/5
'' $@ "$@" $@
\$@ $@ "\$@"
SET "$@"IN<<HEREDOC
sh 3<<\CMD /dev/fd/3
( echo 'set "$@" and \$@ in here-doc' ; echo
set -- '1 "2" 3' 4 "5 6"
su - mikeserv 4<<-UNQUOTED 5<<-\PREQUOTED /dev/fd/4
set -- "$@" "\$@"
echo UNQUOTED; echo $0 "$*"
printf "%s\\t\\t%s\\t\\t%s\\t\\t%s\\n" $(printf "'%s' " "$@") \\
$@ '$@' "$@" '"$@"' "'$@'" \$@ '\$@' "\$@" '"\$@"'
. /dev/fd/5
UNQUOTED
set -- "$@" "\$@"
echo PREQUOTED ; echo $0 "$*"
printf "%s\t\t%s\t\t%s\t\t%s\n" $(printf "'%s' " "$@") \
$@ '$@' "$@" '"$@"' \$@ '\$@' "\$@" '"\$@"'
PREQUOTED
)
CMD
RESULTADO
set "$@" and \$@ in here-doc
UNQUOTED
/dev/fd/3 1 2 3 4 5 6
1 "2" 3 4 5 6 1
2 3 4 5
6 1 "2" 3 4 5 6 1 2 3 4 5 6 "1 "2" 3 4 5 6"
'1 2 3 4 5 6' 1 2 3 4 5 6 $@ 1 2 3 4 5 6
"$@"
PREQUOTED
/dev/fd/5 1 2 3 4 5 6 $@
'1 2 3 4
5 6' '$@' 1 2 3 4 5 6
$@ $@ 1 2 3 4 5 6 $@
"$@" $@ \$@ $@
"\$@"
SET "$@"E MAIS EM<<HEREDOC
sh 3<<\CMD /dev/fd/3
( echo 'set "$@" and \$@ AND additional parameters in here-doc' ; echo
set -- '1 "2" 3' 4 "5 6"
su - mikeserv 4<<-UNQUOTED 5<<-\PREQUOTED /dev/fd/4
set -- "$@" "\$@" '7 "8" 9' 10 "11 12"
echo UNQUOTED; echo $0 "$*"
printf "%s\\t\\t%s\\t\\t%s\\t\\t%s\\n" $(printf "'%s' " "$@") \\
$@ '$@' "$@" '"$@"' "'$@'" \$@ '\$@' "\$@" '"\$@"'
. /dev/fd/5
UNQUOTED
set -- "$@" "\$@" '13 "14" 15' 16 "17 18"
echo PREQUOTED ; echo $0 "$*"
printf "%s\t\t%s\t\t%s\t\t%s\n" $(printf "'%s' " "$@") \
$@ '$@' "$@" '"$@"' \$@ '\$@' "\$@" '"\$@"'
PREQUOTED
)
CMD
RESULTADO
set "$@" and \$@ AND additional parameters in here-doc
UNQUOTED
/dev/fd/3 1 2 3 4 5 6
1 "2" 3 4 5 6 1
2 3 4 5
6 1 "2" 3 4 5 6 1 2 3 4 5 6 "1 "2" 3 4 5 6"
'1 2 3 4 5 6' 1 2 3 4 5 6 7 "8" 9 10
11 12 $@ 1 2 3 4 5 6 7 "8" 9
10 11 12 "$@"
PREQUOTED
/dev/fd/5 1 2 3 4 5 6 7 "8" 9 10 11 12 $@ 13 "14" 15 16 17 18
'1 2 3 4
5 6' '7 "8"
9' '10' '11 12'
'$@' '13 "14" 15'
'16' '17 18' 1 2 3 4 5 6
7 "8" 9 10 11 12 $@
13 "14" 15 16 17 18 $@
1 2 3 4 5 6 7 "8" 9 10 11 12
$@ 13 "14" 15 16 17 18
"$@" $@ \$@ $@
"\$@"
bash 4.2.45as contas de origem e de destino.