i'm trying to open a new screen for a command which using pipe. I have tried many options e.g:
screen "cat ~/input | parallel --colsep '\t' -j 100 -m sh ~/runner.sh {}"
Maybe i'm missing something with file descriptors or something, but searching efforts were in vain. Thanks.
You cannot directly use shell syntax constructs like { code; }
or ;
or &
or |
in arguments you pass to screen
(or parallel
, or xargs
, or etc). The shell will try to parse your command before running it, so anything which looks like
echo | moo |
will be parsed into a pipeline with the commands echo
and moo
and nothing (which is of course a syntax error). If you want to echo
a pair of literal pipe characters, you have to quote them:
echo '| moo |'
If you want the quoted stuff to be evaluated after the shell parses it, there are a couple of options.
screen myscript
and have the actually useful commands in the script file myscript
. (Some useful tools even allow you to use shell functions or even aliases here.)sh -c 'morecommands'
or bash -c 'morecommands'
so that the commands are quoted but end up being executed anyway. This is just another form of encapsulation really, but doesn't require a separate external definition like a script file or shell function.So in your example, you could put your code in a script like ./metarunner
and then just call screen ./metarunner
; or quote the command line like
screen sh -c "parallel --colsep '\t' -j 100 -m sh $HOME/runner.sh {} <$HOME/input"
(I switched ~
to $HOME
here so I could use sh
instead of bash
. If you need nontrivial Bash features or are too lazy to refactor your code into POSIX shell script, obviously use bash -c
instead of sh -c
. See also Difference between sh and bash for what the differences are exactly.)
Tangentially, I also got rid of the useless use of cat
.