How to expand {} from xargs in process substitution?

803 views Asked by At

I try to use gap version 4.10 with xargs as following:

$ echo 1 | xargs -I '{}' gap -b <( echo 'Display("{}");' ) <( echo 'QUIT;')

which returns

{}

However, it should be

1

Following works

$ gap -b <( echo 'Display("123");' ) <( echo 'QUIT;')
123

If you do not have gap v4.10, you can replace gap with cat and still see my problem:

$ echo 1 | xargs -I '{}' cat <( echo 'Display("{}");' ) <( echo 'QUIT;')
Display("{}");
QUIT;

How can I achieve that the return value becomes?

Display("1");
QUIT;

From my point of view, this has nothing to do with gap but the combination of xargs and process substitution in the shell. I have zsh 5.7.1 and GNU bash 5.0.3 available. xargs is GNU version 4.8.0.

Notes:

  • My motivation is that I want to run a gap script in parallel with different parameters from the shell.
  • gap version 4.10 has not yet the option -c <expr> (commit) which would allow me to avoid using process substitution. However, on the compute server, there is only gap version 4.10.0.
2

There are 2 answers

1
chepner On

The process substitutions themselves resolved to file names, not output of the commands inside the substation:

$ echo <(echo foo)
/dev/fd/63

As a result, xargs never sees the {}. It reads 1 from its standard input, but none of the arguments to xargs contain a {}, so no substitution occurs. What you are left with is a single call to gap like

gap -b /dev/fd/63 /dev/fd/62  # The exact paths may differ

and gap, AFAICT, just reads commands from those files and executes them.

If you want to execute the command Display("1"), you need to construct that first, then execute the result. Something like

 # Adjust gap as needed to read from standard input.
echo 1 | xargs -I '{}' echo 'Display("{}"); Quit;' | gap
5
Hotschke On

As @chepner has pointed out, process substitution is performed by the shell before xargs does its {} substitution and so xargs never sees {}.

Creating a shell command as following solved it for me:

echo 1 | xargs -I '{}' zsh -c "gap -b <( echo 'Display(\"{}\");' ) <( echo 'QUIT;')"