Как эта команда законна? «> File1 <file2 cat»

61

Предполагая, что file2уже существует, команда

> file1 < file2 cat

похоже копирует содержимое file2в file1.

Но я не могу понять эту структуру.

Я понимаю, что «Ничто» направлено на file1(создание или удаление его содержания). Тогда содержание file2направляется на file1.

Почему catпосле file2? как узнать, cat file2что операнды не в правильном порядке?

shaqed
источник
11
Какой «правильный порядок»? Можете ли вы предоставить ссылку на некоторый ресурс / учебный материал, где описан «правильный порядок»?
Легкость гонок с Моникой
7
При задании таких вопросов, вы должны указать оболочку; разные имеют разные крайние случаи, особенно в отношении перенаправления.
Хрилис - на забастовку -

Ответы:

117

Прежде чем оболочка выполнит catкоманду в командной строке, она ищет перенаправления.

Есть два перенаправления:

  1. >file1 Это заставит стандартный вывод команды перейти на file1.
  2. <file2 Это сделает стандартный ввод команды из file2.

Тот факт, что эти перенаправления размещаются в неудобном месте в командной строке, не имеет значения.

$ cat <file2 >file1

такой же как

$ <file2 cat >file1

который так же, как

$ <file2 >file1 cat

etc.¹

Обратите внимание, что catутилита во всех этих случаях выполняется без аргументов командной строки . Перенаправления не являются операндами catкоманды, они представляют собой инструкции для оболочки по настройке перенаправлений в команду и из нее (соединяя ее стандартный ввод и вывод с файлами). Оболочка устанавливает перенаправления перед вызовом команды.

Разница между cat fileи cat <file(или, если хотите, <file cat) заключается в том, что в первом случае catутилита сама открывает файл, который задается как операнд в командной строке, для чтения, а во втором случае оболочка будет откройте файл и подключите catк нему поток ввода². Во втором случае catзаметит, что ему не был предоставлен файловый операнд, и автоматически переключится на чтение со своего стандартного ввода. Это особенность catнекоторых других утилит, а не то, что делают все утилиты.

catтакже будет читать со своего стандартного ввода, если ему дан операнд -. Опять же, это особенное только для catнекоторых других утилит (то есть ничего, что делает оболочка ). Для использования catна файл в текущем каталоге, имя которого является - , добавить путь к имени файла, например ./-.

Order Порядок перенаправлений по-прежнему важен при некоторых обстоятельствах; С cat <file2 >file1, например, file1не будет усечено, если file2недоступно (перенаправления анализируются слева направо). Относительное размещение слова catвсе же произвольно и не повлияет на это.

² См. Также вопрос « cat выдает другую ошибку при открытии несуществующего файла ».


Тот факт, что оболочка устанавливает перенаправления еще до того, как выполнить команду в командной строке, объясняет, почему подобные вещи терпят неудачу, и в результате получается пустой выходной файл:

$ sort file >file

Здесь оболочка усекает (очищает) файл fileперед выполнением sort fileи подключением sortстандартного вывода к файлу. Затем sortутилита откроет fileи отсортирует его содержимое (что является ничем). Результат (ничего) передается через стандартный поток вывода в file.

Средство защиты в данном конкретном случае (для сортировки файла "на месте")

$ sort -o file file

или же

$ sort file >file.sorted && mv file.sorted file

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


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

«Простая команда» - это последовательность необязательных присвоений и перенаправлений переменных, в любой последовательности, за которыми могут следовать слова и перенаправления, оканчивающиеся оператором управления. [ref: POSIX Shell Command Language 2.9.1 Простые команды]

А также о том, что перенаправление не является частью операндов утилиты:

Необязательный номер, оператор перенаправления и слово не должны появляться в аргументах, предоставляемых команде, которая будет выполнена (если есть). [ref: Язык команд оболочки POSIX 2.7 Перенаправление]

Кусалананда
источник
14
@Steve Свобода перемещения перенаправлений может быть использована для того, чтобы сделать некоторые команды более понятными, например, конвейер с перенаправлением ввода вначале <in foo | bar >outупорядочивает все в логическом порядке. Мне также нравится, если echo >&2 Something bad happenedдля вывода ошибок из сценариев оболочки. Но >out <in catэто просто запутанность
2
Как может sort file >fileбыть правильно выполнено?
10
11
@setht С sort -o file file.
Кусалананда
6
Отличный ответ. Обратите внимание, что порядок имеет значение. < file1 > file2 catбыло бы лучше, чем > file2 < file1 cat, если бы его нельзя было обрезать , чтобы избежать file2его усечения file1.
Стефан
3
Что следует знать: при связывании POSIX с фрагментами HTML лучше указывать точное издание (например, pubs.opengroup.org/onlinepubs/9699919799.2016edition ), поскольку известно, что фрагменты изменяются между выпусками одной и той же редакции спецификации. (многие ссылки в ответах на этом сайте, в том числе и мои, в настоящее время неверны, поскольку фрагменты указывают на неправильное место после выпуска издания 2016 года).
Стефан