Каковы операторы управления и перенаправления оболочки?

Я часто вижу онлайн-учебники, которые соединяют различные команды с разными символами. Например:

command1 |  command2
command1 &  command2
command1 || command2    
command1 && command2

Другие, похоже, подключают команды к файлам:

command1  > file1
command1  >> file1

Что это за вещи? Как они называются? Что они делают? Их больше?


Мета-поток об этом вопросе. .

178 голосов | спросил terdon 6 +04002014-10-06T06:18:44+04:00312014bEurope/MoscowMon, 06 Oct 2014 06:18:44 +0400 2014, 06:18:44

3 ответа


240

Они называются операторами оболочки, и да, их больше. Я дам краткий обзор наиболее распространенных среди двух основных классов, операторов управления и Приоритет логических операторов оболочки & amp ;, || для получения дополнительной информации.

  • ||: Это оператор «нет», используемый для отрицания статуса возврата команды. «Возврат 0», если команда возвращает ненулевой статус, возвращает 1, если он возвращает статус 0.

    !
  • A.3 Оператор труб

    • &&: оператор трубы, он передает вывод одной команды в качестве входного сигнала другому. Команда, построенная из оператора трубы, называется конвейер .

      &

      Любой вывод, напечатанный ;, передается как вход в ;;.

    • |: Это сокращение для |& в bash и zsh. Он передает как стандартный вывод, так и стандартную ошибку одной команды в качестве входа в другую.

      (

    A.4 Пунктуация другого списка

    ) используется только для обозначения конца case statement . Ksh, bash и zsh также поддерживают ;, чтобы перейти к следующему случаю и command1 ; command2 (не в ATT ksh) для продолжения и проверки последующих случаев.

    command1 и command2 используются групповые команды и запустить их в подоболочке. ; и ; также команды группы, но не запускайте их в подоболочке. См. этот ответ для обсуждения различных типов круглых скобок, скобок и фигурные скобки в синтаксисе оболочки.

    В. Операторы перенаправления

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

    • ;: вводит команду в команду.

      &

      Вышеуказанная команда command1 & command2 будет содержать содержимое command1.

    • command2: тот же, что и выше, но файл открыт в режиме read + write вместо только для чтения :

      command1

      Если файл не существует, он будет создан.

      Этот оператор редко используется, потому что команды обычно только читают из своего stdin, хотя он может пригодиться в ряд конкретных ситуаций .

    • command1: Направляет вывод команды в файл.

      &&

      Вышеуказанное сохранит вывод команды command1 && command2 как command2. Если файл существует, его содержимое будет перезаписано, а если оно не существует, оно будет создано.

      Этот оператор также часто используется для выбора, следует ли что-то печатать на стандартной ошибке или стандартный вывод :

      command1

      В приведенном выше примере command1 перенаправляет стандартный вывод, а if command1 then command2 else false fi перенаправляет стандартную ошибку. Вывод также можно перенаправить с помощью if command1; then command2; fi, но, поскольку это значение по умолчанию, || обычно опускается, и оно написано просто как command1 || command2 .

      Итак, чтобы запустить команду command2 на command1 и сохранить ее вывод в if command1 then true else command2 fi и любые сообщения об ошибках в if ! command1; then command2; fi:

      &&
    • ||: То же, что и !, но перезапишет цель, даже если оболочка настроена на отказ от перезаписывания (с помощью ! command1 или |).

       command1 | command2
      

      Если command1 существует, вывод команды command2 заменит его содержимое. Если он не существует, он будет создан.

    • |&: имеет то же значение, что и 2>&1 |, за исключением того, что если целевой файл существует, новые данные добавляются.

      command1 |& command2
      

      Если ;; существует, вывод команды ;& будет добавлен к нему, после того, что уже есть в нем. Если он не существует, он будет создан.

    • ;;&, (, )

      }

      Как стандартная ошибка, так и стандартный вывод команды < будут сохранены в command < file.txt , переписав его содержимое или создав его, если он не существует.

      command

      Как указано выше, за исключением того, что если file.txt существует, к нему будут добавлены вывод и ошибка команды <>.

      Вариант command <> file.txt исходит из >, а вариант command > out.txt - csh (десятилетия назад). Они оба конфликтуют с другими операторами оболочки POSIX и не должны использоваться в портативных сценариях command.

    • out.txt: здесь документ. Он часто используется для печати многострочных строк.

      command >out.txt 2>error.txt
      

      Здесь > будет принимать все, пока не найдет следующее вхождение 2>, 1> в приведенном выше примере в качестве ввода. Хотя 1 часто > или его вариации, это может быть любая буквенно-цифровая (и не только) строка, которая вам нравится. Когда цитируется command, текст в документе здесь обрабатывается буквально и не выполняется никаких расширений (например, для переменных). Если он не определен, переменные будут расширены. Для получения дополнительной информации см. Раздел руководство bash .

      Если вы хотите подключить вывод команды file.txt непосредственно в другую команду или команды, вы должны поместить канал в ту же строку, что и out.txt, вы не можете поместить его после окончания WORD или в следующую строку. Например:

      error.txt
    • command < file.txt > out.txt 2> error.txt : Здесь строки, аналогичные этим документам, но предназначенные для одной строки. Они существуют только в порте Unix или rc (где он возник), zsh, некоторые реализации ksh, yash и bash.

      Команда
      >|

      Все, что указано как >, расширяется, и его значение передается как вход в команду set -C. Это часто используется для передачи содержимого переменных в качестве ввода команды. Например:

      set -o noclobber

    Несколько других операторов (command >| out.txt , out.txt command) могут быть использованы для закрыть или дублировать дескрипторы файлов. Подробнее о них см. В соответствующем разделе руководства вашей оболочки ( здесь , например, для bash).

    Это распространяется только на наиболее распространенные операторы оболочек, подобных Bourne. Некоторые оболочки имеют несколько дополнительных операторов перенаправления.

    Ksh, bash и zsh также имеют конструкции >>, > и command >> out.txt (этот последний в out.txt). Это не перенаправления, а замещение процесса .

    ответил W8WCA 13 J000000Friday18 2018, 16:19:59
    44

    Предупреждение относительно â € °> â € ™

    Unix-новички, которые только что узнали о перенаправлении ввода-вывода (< и >) часто пробуйте такие вещи, как

     команда  â € |  input_file >  the_same_file 

    или

     команда  â € | < file >  the_same_file 

    или, почти эквивалентно,

    cat  файл  |  команда  â | |>  the_same_file 

    (grep, sed, cut, sort) и spell примеры команд что люди склонны использовать в таких конструкциях.) Â Пользователи с удивлением обнаруживают, что эти сценарии приводят к тому, что файл становится пустым.

    Нюанс, который, похоже, не упоминается в другом ответе, может быть найден скрытым в первом предложении раздела Перенаправление bash (1) :

      

    Перед выполнением команды его ввод и вывод могут быть перенаправлены   используя специальную нотацию, интерпретируемую оболочкой.

    Первые пять слов должны быть полужирным, курсивом, подчеркнутым, увеличенным, мигающим, окрашен в красный цвет и отмечен значком восклицательный знак в красном треугольнике, чтобы подчеркнуть тот факт, что оболочка выполняет запрошенное перенаправление (ы) перед выполнением команды . И помните также

      

    Перенаправление вывода приводит к тому, что файл открывается для записи â € |.   Если файл не существует, он создается; если он существует, он усекается до нулевого размера.

    1. Итак, в этом примере:

       sort roster > roster
      

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

    2. Можно было бы наивно ожидать, что

       tr "[:upper:]" "[:lower:]" < poem > poem
      

      может быть лучше. Поскольку оболочка обрабатывает перенаправления слева направо, он открывает poem для чтения (для стандартного ввода tr)) прежде чем он откроет его для записи (для стандартного вывода). Но это не помогает. Хотя эта последовательность операций дает две файловые дескрипторы, они оба указывают на один и тот же файл. Когда оболочка открывает файл для чтения, содержимое все еще там, но они до сих пор сбиваются, прежде чем программа будет выполнена.

    Итак, что с этим делать?

    Решения включают:

    • Проверьте, будет ли программа, которую вы запускаете имеет собственную, внутреннюю, возможность указывать, где идет выход. Это часто указывается токеном -o (или --output=). В частности,

       sort roster -o roster
      

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

       sort roster > roster
      

      за исключением того, что в первом случае программа sort открывает выходной файл. И это достаточно разумно, чтобы не открывать выходной файл до после он прочитал все входные файлы.

      Аналогично, по крайней мере некоторые версии sed имеют параметр -i (изменить i n место) который может использоваться для записи вывода обратно во входной файл (опять же, после все входные данные были прочитаны). Редакторы вроде ed /ex, emacs, pico и vi /vim разрешить пользователю редактировать текстовый файл и сохранять отредактированный текст в исходном файле. Обратите внимание, что ed (по крайней мере) может использоваться не интерактивно.

      • vi имеет связанную функцию. Если вы введете :%!command Enter , он будет записывать содержимое буфера редактирования в команду command , читать вывод, и вставьте его в буфер (заменив исходное содержимое).
    • Простой, но эффективный:

       команда  â € |  input_file >  temp_file  & & & mv  temp_file   input_file 

      Это имеет недостаток, что если input_file является ссылкой, он (вероятно) будет заменен отдельным файлом. Кроме того, новый файл будет принадлежать вам, с защитой по умолчанию. В частности, это сопряжено с риском того, что файл будет в конечном итоге удобочитаемым, даже если исходный input_file не был.

      Варианты:

      • commandinput_file > temp_file && cp temp_file input_file && rm temp_file
        который будет (потенциально) оставить temp_file всемирно читаемый. Дажелучше:
      • cp input_file temp_file && commandtemp_file > input_file && rm temp_file
        Они сохраняют статус ссылки, владельца и режим (защиту) файла, потенциально за счет вдвое большего объема ввода-вывода. (Возможно, вам понадобится опция -a или -p на cp чтобы сказать, чтобы сохранить атрибуты.)
      • commandinput_file > temp_file &&
        cp --attributes-only --preserve=all input_file temp_file &&
        mv temp_file input_file
        (разбивается на отдельные строки только для удобства чтения). Это сохраняет режим файла (и, если вы root, владелец), но делает его принадлежащим вам (если вы не root), и делает его новым, отдельным файлом.
    • Этот блог («Редактирование файлов на месте») предлагает и объясняет

      {rm  input_file  & & & & &  команда  â | |>  входной_файл ; } < input_file 

      Это требует, чтобы команда command могла обрабатывать стандартный ввод (но почти все фильтры могут). Сам блог называет это рискованным kludge и препятствует его использованию. И это также создаст новый отдельный файл (не связанный ни с чем), принадлежащих вам и с разрешениями по умолчанию.

    • Пакет moreutils имеет команду под названием sponge:

       команда  â € |  input_file  | sponge  the_same_file 

      Подробнее см. этот ответ .

    Вот что-то, что стало для меня полной неожиданностью: syntaxerror говорит :

      

    [Большинство этих решений] выйдет из строя в файловой системе только для чтения,   где «только для чтения» означает, что ваш $HOME будет доступен для записи,   но /tmp будет только для чтения (по умолчанию).   Например, если у вас есть Ubuntu, и вы загрузились в консоль восстановления,   это обычно бывает.   Кроме того, оператор здесь-документа <<< также не работает,   поскольку для этого требуется /tmp читать /писать   потому что он также напишет временный файл.
      (см. это вопрос включает в себя вывод strace â € ™ d)

    В этом случае может работать следующее:

    • Только для продвинутых пользователей: Если ваша команда гарантирует получение одинакового объема выходных данных поскольку есть вход (например, sort) или tr без -d или -s), можешь попробовать
       команда  â € |  input_file  | dd of =  the_same_file  conv = notrunc
      См. этот ответ и этот ответ для получения дополнительной информации, включая объяснение вышесказанного, и альтернативы, которые работают если ваша команда гарантирует получение одинакового объема выходных данных поскольку есть вход или меньше (например, grep или cut)). Эти ответы имеют то преимущество, что они не требуют свободного места (или они требуют очень мало). Ответы выше формы commandinput_file > temp_file && … явно необходимо, чтобы было достаточно свободного места для системы для одновременного хранения всего файла ввода (старого) и вывода (нового) файла; это не очевидно для большинства других решений (например, sed -i и sponge). Исключение: sort … | dd …, вероятно, потребует много свободного места, потому что sort должен прочитать весь свой вклад, прежде чем он сможет записать любой вывод, и, вероятно, буферизирует большинство, если не все эти данные во временном файле.
    • Только для продвинутых пользователей:
       command  â € |  input_file  1 <>  the_same_file 
      может быть эквивалентен ответу dd, выше. Синтаксис n<> file открывает именованный файл в файловом дескрипторе n для ввода и вывода , без усечения его - вид комбинации n< и n> . Примечание. Некоторые программы (например, cat и grep) могут отказаться от запуска в этом сценарии потому что они могут обнаружить, что вход и выход являются одним и тем же файлом. См. этот ответ для обсуждения вышеизложенного, и скрипт, который заставляет этот ответ работать, если ваша команда гарантирована для получения того же объема выходных данных, что и вход или меньше .
      Предупреждение: я не испытал сценарий Питера, поэтому я не ручаюсь за него.

    Итак, в чем вопрос?

    Это была популярная тема в U & L; он рассматривается в следующих вопросах:

    â € | и это не считается Super User или Ask Ubuntu. Я включил много информации из ответов на вышеуказанные вопросы здесь, в этом ответе, но не все. (I.e., для получения дополнительной информации, прочитайте перечисленные выше вопросы и их ответы.)

    P.S. У меня есть no связь с блоком, который я привел выше.

    ответил Scott 21 FebruaryEurope/MoscowbSat, 21 Feb 2015 23:42:35 +0300000000pmSat, 21 Feb 2015 23:42:35 +030015 2015, 23:42:35
    20

    Дополнительные наблюдения над ;, &, ( и )

    • Обратите внимание, что некоторые команды в ответе terdon могут быть нулевыми. Например, вы можете сказать

       command1 ;
      

      (без command2). Это эквивалентно

       command1
      

      (т. е. он просто запускает command1) на переднем плане и ждет его завершения. Сравнительно,

       command1 &
      

      (без command2) запустит command1 в фоновом режиме а затем немедленно выпустите приглашение оболочки.

    • В отличие от этого command1 &&, command1 || и command1 | не имеет никакого смысла. Если вы наберете один из них, оболочка (вероятно) предположит, что команда продолжается на другую строку. Он отобразит вторичное (продолжение) приглашение оболочки, который обычно устанавливается в > и продолжает читать. В сценарии оболочки он просто прочитает следующую строку и добавьте его к тому, что он уже прочитал. (Остерегайтесь: возможно, это не так, как вы хотите.)

      Примечание. Некоторые версии некоторых оболочек могут обрабатывать такие неполные команды как ошибки. В таких случаях (или, фактически, в любом случае, когда у вас длинная команда) вы можете поместить обратную косую черту (\) в конце строки чтобы командная оболочка продолжала читать команду на другой строке:

       command1  &&  \
      command2
      

      или

       find starting-directory -mindepth 3 -maxdepth 5 -iname "*.some_extension" -type f \
                              -newer some_existing_file -user fred -readable -print
      
    • Как говорит Тердон, ( и ) можно использовать для группировки команд. Утверждение о том, что они «не очень актуальны» для этой дискуссии, является спорным. Некоторые команды в ответе terdon могут быть командой groups . Например,

       ( command1 ; command2 )  &&  ( command3; command4 )
      

      делает следующее:

      • Запустите command1 и дождитесь окончания.
      • Затем, независимо от результата запуска этой первой команды, запустите команду command2 и дождитесь ее завершения.
      • Затем, если command2 преуспел,

        • Запустите command3 и дождитесь окончания.
        • Затем, независимо от результата выполнения этой команды, запустите command4 и дождитесь его завершения.

        Если не удалось выполнить команду command2, остановите обработку командной строки.

    • Внешние скобки, | связывают очень сильно, поэтому

       command1 | command2 || command3
      

      эквивалентно

       ( command1 | command2 )  ||  command3
      

      и && и || связывают более строгие, чем ;, поэтому

       command1 && command2 ; command3
      

      эквивалентно

       ( command1 && command2 ) ;  command3
      

      i.e., command3 будет выполняться независимо от состояния выхода команды command1 и /или command2.

    ответил G-Man 6 +04002014-10-06T22:05:35+04:00312014bEurope/MoscowMon, 06 Oct 2014 22:05:35 +0400 2014, 22:05:35

    Похожие вопросы

    Популярные теги

    security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132