I'm quite new to linux shell scripting and have a question:
1.) why does the command
test1="leafpad" && coproc exec "$test1"
work in bash (commandline, GNU bash 4.4.12 on a debian derivate linux), but the command
test1="coproc" && exec "$test1" leafpad
does not? Error messages: bash: exec: coproc: Not found.
whereas
coproc leafpad
does work as expected.
How this command must be correct quouted to make it work? I've tried already
test1=`coproc` && exec "$test1" leafpad
test1='coproc' && exec "$test1" leafpad
test1="'coproc'" && exec "$test1" leafpad
test1=`coproc` && exec '$test1' leafpad
test1=`coproc` && exec `$test1` leafpad
test1="coproc" && exec $test1 leafpad
test1=`coproc` && exec $test1 leafpad
and some more variations, but none of them works.
2.) This was the test on commandline only. But what I rather need is to do this within a script: So I'm sure there are to be done some additional quotations or masquerading of special characters.
Background: I have to execute a command, containing many arguments, some of them replaced by variables. Think of something like yad with all its possible arguments in a couple of lines, but let's create an easier example:
my_codeset="437"
my_line="20"
my_filename="somthing.txt"
if [ $value == 0 ]; then my_tabwidth='--tab-width=10'; else my_tabwidth=""; fi # set tabs or not
leafpad --codeset="$my_codeset" "$my_tabwidth" --jump="$my_line" "$my_filename"
wherein the variables given are subject of change, as a function of user interaction before.
Now this complete command (which is about 6 lines of code in original), needs to be executed in two variants: one time headed by coproc, and another time not, as a function of an conditional branch.
so what I want is:
if [ $something == 1 ]; then copr_this="coproc"; else copr_this=""; fi
exec '$copr_this' <mycommand, with all its quoted arguments>
instead of
if [ something == 0]; then
lengthy command here
else
coproc lengthy command here, exactly repeated.
fi
I tried to manage it the other way around already, which was to put the complete lengthy command in a variable, and execute it in an conditional branch:
my_command=`lengthy command with some arguments $arg1 $arg2 ...`
if...
exec "$my_command"
else
coproc exec "$my_command"
fi
which stopped with error message "not found" also. Different ways of quoting didn't solve it, but produced different error messages only. I didn't manage to find out the correct quoting for this task. How shold this qouting read correctly?
For sure I could repeat the 6 lines of command in the code, but I'm quite sure this could be done more convenient.
As stated in the beginning: The indirect command execution works on commandline (and within script also), as long as coproc isn't involved. I cant't get it to work with coproc.
Any help and hints appreciated.
Update after first answer from @Socowi:
Thank you for your comprehensive and quick answer, Socowi. You are obviously right about coproc
not beeing a command. So I understand now why my attempts had to fail. The exec
command was added only during my experiments. I had started without this, but after having no success I thought it could help. It was an act of desperation merely. The backward quotes in the line my_command=`lengthy command with some arguments $arg1 $arg2 ...`
were a typo, there should have been normal quotes, as you pointed out, since I intended to execute the command within the if
of course. I'll probably head for the way you directed me to, using function {...}
within script. But having experimented on this question in the meantime, I came to an astonishing solution: Astonishing for me, because of the difference between coproc
not beeing a command and leafpad
with its binary beeing a command. So it should be clear that test1='coproc' && test2='leafpad' && "$test1 $test2"
will fail with error message bash: coproc leafpad: command not found.
, which is true. But now: why would test1='coproc' && test2='leafpad' && /bin/bash -c "$test1 $test2"
do the job, starting leafpad, allowing to enter further commands in bash parallel, just as if I had entered leafpad &
only? But this time executing both, the builtin (or keyword?) and the command, from a variable, which was refused when trying to enter it directly in the first bash instance. What is true for the first instance of bash should be true for the second also, or do I have a false perspective? Why does it work this way? Does the -c
option do anything else than to execute the command?