Eu tenho um comando com vários argumentos:
my_command --arg1 <arg1> \
--arg2 <arg2> \
--arg3 <arg3>
Eu envolvi a invocação de my_command
em uma função que configura os valores para os vários argumentos, que podem ou não ser passados:
run_my_command() {
if [[ ... ]]; then
ARG1FLAGS="--arg1 $ARG1"
else
ARG1FLAGS=''
fi
if [[ ... ]]; then
ARG2FLAGS="--arg2 $ARG2"
else
ARG2FLAGS=''
fi
if [[ ... ]]; then
ARG3FLAGS="--arg3 $ARG3"
else
ARG3FLAGS=''
fi
my_command $ARG1FLAGS \
$ARG2FLAGS \
$ARG3FLAGS
}
Em alguns casos, é necessário passar um argumento de nome de arquivo para my_command
:
run_my_command() {
# ...
if [[ ... ]]; then
FILEARG="--input_file $SOME_FILE"
else
FILEARG=''
fi
my_command $FILEARG \
...
}
Tudo isso funciona bem. Agora, gostaria de usar condicionalmente a substituição de processo para FILEARG
, mas é claro que isso não funciona:
run_my_command() {
# ...
if [[ ... ]]; then
FILEFLAG='--input_file'
FILEARG=<(other_cmd)
else
FILEARG=''
fi
my_command $FILEFLAG $FILEARG \
...
}
porque no momento em que my_command
é executado, $FILEARG
, um canal anônimo com aparência de /dev/fd/63
, já está fechado.
No momento, resolvi isso colocando todos os my_command
em uma condição:
run_my_command() {
# Get ARG1, ARG2, ARG3...
if [[ ... ]]; then
my_command --input_file <(other_cmd) \
$ARG1FLAGS \
$ARG2FLAGS \
$ARG3FLAGS
else
my_command $ARG1FLAGS \
$ARG2FLAGS \
$ARG3FLAGS
fi
}
mas não gosto da duplicação. Eu sinto que talvez haja algo que eu possa fazer com eval
, ou possivelmente eu posso colocar my_command
em outra função, mas eu ainda não descobri. Como posso usar condicionalmente a substituição de processos para gerar um arquivo do qual my_command
possa ler sem duplicar a chamada inteira para my_command
?
Note que estou executando o bash 4.4.19. Para minha considerável surpresa, o bash 3.2.57 parece se comportar da maneira que o wiki do Bash Hackers, abaixo, sugere:
doit() {
local -r FOO=<(echo hi)
cat $FOO
}
doit
# bash 3.2.57:
$ ./test.sh
hi
# bash 4.4.19:
$ ./test.sh
cat: /dev/fd/63: Bad file descriptor
Aqui estão algumas perguntas que examinei, mas das quais não consegui obter uma resposta em funcionamento:
Além disso, as notas do wiki do Bash Hackers são bastante enigmáticas:
If a process substitution is expanded as an argument to a function, expanded to an environment variable during calling of a function, or expanded to any assignment within a function, the process substitution will be "held open" for use by any command within the function or its callees, until the function in which it was set returns. If the same variable is set again within a callee, unless the new variable is local, the previous process substitution is closed and will be unavailable to the caller when the callee returns.
In essence, process substitutions expanded to variables within functions remain open until the function in which the process substitution occured returns - even when assigned to locals that were set by a function's caller. Dynamic scope doesn't protect them from closing.
mas eu não consegui obter uma substituição de processo "mantida aberta" apenas atribuindo-a a uma variável em uma função.