Трубы и перенаправление, связывающие приоритет с дизъюнктами, конъюнктами и т. Д.?

8

Я знаю об относительной приоритетности операторов ';', '&', '&&' или '||'

http://www.gnu.org/software/bash/manual/bashref.html#Lists

но когда в картину входят трубы, и '&&' я изо всех сил пытаюсь понять силу связывания и либо натыкаюсь на правильную команду, либо просто сдаюсь

Что является обязательным приоритетом '|' и «>» по сравнению с вышеупомянутым?

Пример, где я запутался:

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

Цель описанного выше - создать миниатюру тогда и только тогда, когда ее еще нет (я запускаю ежедневный cronjob). И мне не нравится огромное количество вывода ffmpeg, когда нет ошибок (что не является способом Unix). Есть и другие ситуации, поэтому не начинайте давать мне советы, в которых используются отдельные утверждения или специальные опции, характерные для этих программ. Я хочу понять обязательный приоритет.

Шридхар Сарнобат
источник
Очень полезно - я бы пометил это правильно, если бы это был ответ. Еще один вопрос - как мне изменить приоритет? В теории я думаю {... }должно работать. Я мог бы попробовать это бессистемно и не получил ожидаемых результатов.
Шридхар Сарнобат

Ответы:

12

Краткий ответ таков <, >и их варианты имеют наивысший приоритет связывания (самое жесткое связывание), за которым следует |, а затем &&и ||, а затем ;и &. Таким образом, только по echo "Thumbnail creation failed"трубопроводу tee.

Несколько более длинный ответ указывает на то, что на самом деле наивысший приоритет имеет группировка, которая может быть указана в скобках или фигурных скобках. Например,

A  &&  (B; C)

а также

A  &&  { B; C;}

примерно эквивалентны

if A
then
    B
    C
fi

Ноты:

  • Скобки дают вам скорлупу; команды Bи Cвыполняются в дочернем процессе. Поэтому такие команды, как присвоение переменных, не cd будут влиять на родительскую оболочку. Команды в фигурных скобках выполняются в том же процессе, что и Aкоманда. Следовательно, конструкция скобки A && { B; C;}ближе к if- then- elseконструкции.
  • В синтаксисе скобок должен быть пробел после {и a ;(или a &, или перевод строки) перед }.

Подробнее читайте в разделе Что такое операторы управления и перенаправления оболочки? и когда «если» не нужно? (особенно мои ответы).

Для получения дополнительной информации см. Справочную страницу bash (1) и спецификацию / определение POSIX языка команд оболочки , в частности раздел 2.9, Команды оболочки и раздел 2.10.2, Правила грамматики оболочки . Это попытка предоставить некоторый контекст для вышеупомянутого:

  • Вещи как

    • 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

    все считаются «простыми командами».

  • Вещи как
      простая_команда 1   |   простая_команда 2   |   простая_команда 3
    являются «трубопроводами». Грамматика устанавливает строительные блоки и строит на них, как это типично для формальных грамматик, подобных этой (и для языков программирования, таких как C), поэтому отдельная «простая команда» считается «конвейером», даже если она не содержит трубка. Это не имеет (семантического) смысла для того, чтобы присвоение переменной было компонентом конвейера, но вещи как x=1 | od -abили ls -laR | z=0синтаксически допустимы.
  • Вещи как
      трубопровод 1   &&   трубопровод 2   ||   трубопровод 3
      называются «списки» bash и «И-ИЛИ списки» POSIX. Опять же, отдельный «конвейер» или даже отдельная «простая команда» считается «списком И-ИЛИ», даже если он не содержит И или ИЛИ.
    • Когда вы добираетесь до таких вещей, как
        И-ИЛИ список 1  И   И-ИЛИ список 2  ;   И-ИЛИ Список 3
        номенклатура начинает становиться немного противоречивой. Баш также называет эти «списки»; POSIX называет их «списки», «составные списки» и (редко) «термины». Опять же, отдельный список «И-ИЛИ», «конвейер» или даже отдельная «простая команда» считается «списком», даже если он не содержит a &или a ;.
      • Вещи как
          ( составной_лист )
          а также
            {  составной_лист ;}
            и команды управления потоком ( for,  if- then- else,  whileи т. д.) называются «составными командами». 
          • В приведенных выше примерах, вероятно , имеет самый смысл интерпретировать A, Bи Cбыть трубопроводов. Помните, что «конвейер» может быть отдельной «простой командой»; это не должно содержать трубу.

            G-Man говорит: «Восстанови Монику»
            источник
            1
            Спасибо за подробное объяснение о роли (.. )и {.. }. Из предыдущего неудачного опыта я пришел к выводу, что круглые скобки используются только в контексте «динамических команд» (т. $(Е. )), Так как я едва мог заставить их делать что-либо в отношении ассоциативности.
            Шридхар Сарнобат