Conheço a relativa precedência de ligação dos operadores ';', '&', '&&' ou '||'
http://www.gnu.org/software/bash/manual/bashref.html#Lists
mas quando os tubos entram em cena, junto com '&&', luto para entender a força da amarração e tropeço em um comando correto ou simplesmente desisto.
Qual é a precedência vinculativa de '|' e '>' comparado ao acima?
Exemplo onde eu fico confuso:
ls _thumbnails/video.mp4.jpg 2>/dev/null
&& echo "thumbnail already generated. Not regenerating" \
&& exit \
|| ffmpeg_thumbnail_create video.mp4 2>/dev/null \
&& ls _thumbnails/video.mp4.jpg \
&& echo "Thumbnail successfully created" \
&& exit \
|| echo "Thumbnail creation failed" \
| tee ~/thumbnails.log
O objetivo do exposto acima é criar uma miniatura, se e somente se ainda não estiver presente (eu executo um cronjob diário). E eu não gosto da enorme quantidade de saída do ffmpeg quando não há erro (que não é o caminho do Unix). Também existem outras situações, portanto, não comece a me dar conselhos que usem instruções separadas ou opções especiais específicas para esses programas. Eu quero entender a precedência vinculativa.
fonte
{
...}
deveria funcionar. Eu poderia ter tentado sistematicamente e não obtive os resultados esperados.Respostas:
A resposta é que
<
,>
e suas variantes têm a prioridade mais alta de ligação (ligação mais apertada), seguido por|
, seguido por&&
e||
, seguida de;
e&
. Portanto, apenas oecho "Thumbnail creation failed"
é canalizado para otee
.Uma resposta um pouco mais longa indicaria que a maior precedência é realmente o agrupamento, que pode ser indicado entre parênteses ou chaves. Por exemplo,
e
são aproximadamente equivalentes a
Notas:
B
eC
executados em um processo filho. Portanto, comandos como atribuições de variáveis oucd
não terão efeito no shell pai. Os comandos entre chaves são executados no mesmo processo que oA
comando. Portanto, a construção entre chavesA && { B; C;}
está mais próxima da construçãoif
-then
-else
.{
uma;
(ou a&
ou nova linha) antes da}
.Para uma leitura mais detalhada, consulte Quais são os operadores de controle e redirecionamento do shell? e Quando o 'se' não é necessário? (particularmente minhas respostas).
Para uma leitura ainda mais detalhada, consulte a página do manual bash (1) e a especificação / definição POSIX da Linguagem de Comando do Shell , especificamente a Seção 2.9, Comandos do Shell e a Seção 2.10.2, Regras gramaticais da Shell . Esta é uma tentativa de fornecer algum contexto para o acima exposto:
Coisas como
myVar=42
IFS= read a
date
cd /some/directory
ls -laR dir1 dir2
cat foo* > /tmp/allfoo
ls -laR dir{1,2}
find . -type f -name "foo*" -print > /tmp/output 2> /dev/null
> newfile
[ -f catfood ]
exit
são todos considerados "comandos simples".
x=1 | od -ab
ouls -laR | z=0
são sintaticamente válidas.são chamados de "listas" pelo bash e "AND-OR lists" pelo POSIX. Novamente, um "pipeline" individual ou mesmo um "comando simples" individual é considerado uma "lista AND-OR", mesmo que não contenha um AND ou um OR.
a nomenclatura começa a ficar um pouco inconsistente. Bash chama essas "listas" também; O POSIX os chama de "listas", "listas compostas" e (raramente) "termos". Novamente, uma "lista E-OU" individual, "pipeline" ou mesmo um "comando simples" individual é considerado uma "lista", mesmo que não contenha a
&
ou a;
.e
e os comandos de controlo de fluxo (
for
,if
-then
-else
,while
, etc.) são chamados “compostos” comandos.Nos exemplos acima, provavelmente faz mais sentido para interpretar
A
,B
eC
para ser condutas. Lembre-se, um "pipeline" pode ser um "comando simples" individual; não precisa conter um cano.fonte
(
..)
e{
..}
. Concluí, por experiências ruins anteriores, que colchetes eram usados apenas no contexto de "comandos dinâmicos" (isto é$(
...)
), pois eu mal conseguia que eles fizessem qualquer coisa no que se refere à associatividade.