cp a b && mv b c && rm a &
está correto. &
tem precedência menor que &&
. De fato, &
tem precedência menor do que qualquer coisa diferente de ;
e nova linha: &
está na mesma categoria sintática que ;
, a diferença é que ;
executa a lista de comandos em primeiro plano enquanto &
roda em segundo plano. Você pode testar isso por si mesmo:
$ dash -c 'sleep 2 && echo waited & echo backgrounded'
backgrounded
$ waited
Mesmo com pdksh, ksh93, bash, csh, tcsh.
A exceção é zsh, que é estranhamente incompatível. Isso é documentado no manual :
If a sublist is terminated by a
&
,&|
, or&!
, the shell executes the last pipeline in it in the background, and does not wait for it to finish (note the difference from other shells which execute the whole sublist in the background).
Infelizmente, o zsh se comporta dessa maneira mesmo no modo de compatibilidade sh ou ksh. Para garantir que todo o comando seja executado em segundo plano, coloque chaves ou parênteses em torno dele. Parênteses criam um subshell enquanto que chaves não, mas isso é irrelevante (exceto como uma micro otimização em alguns shells) já que um comando em segundo plano está em uma subshell de qualquer maneira.
{ cp a b && mv b c && rm a; } &