Указано ли это поведение хвоста в командах группировки в POSIX?

mv file.txt .. и mv file.txt ../file.txt имейте точно тот же эффект. Существует тонкое различие в mv:

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

Так, если dir является каталогом:

mv file1 file2 file3 dir  # Moves the files there
mv file dir               # Moves one file
mv file dir/newname       # Moves file, new name
mv file newfile           # Just renames
7
01.11.2015, 01:36
1 ответ

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

И да, он соответствует стандарту POSIX.

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

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html :

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

Для head возможность делать это для файла без возможности поиска означало бы, что ему пришлось бы читать по одному байту за раз, что было бы ужасно неэффективно ». Это то, что читает или строка утилита do или GNU sed с параметром -u .

Таким образом, вы можете заменить head -n 20 на gsed -u 20q , если хотите такого поведения.

Хотя здесь вы бы предпочли:

sed -e 1b -e '$b' -e d

вместо этого. Здесь только один вызов инструмента, поэтому нет проблем с внутренним буфером, который нельзя использовать совместно между двумя вызовами инструмента. Однако обратите внимание, что для больших файлов это будет менее эффективно, поскольку sed читает весь файл, а для файлов с возможностью поиска tail пропустит большую часть, ища ближе к концу файла.

См. Соответствующее обсуждение буферизации на Почему использование цикла оболочки для обработки текста считается плохой практикой? .

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

Так, например, в:

{ cat; tail -n 1; } < file

Хотя tail может искать назад к последней строке файла , это не так. Его stdin - пустой поток, поскольку cat оставил курсор в конце файла; не разрешено восстанавливать данные из этого потока, ища дальше назад в файле.

(Текст выше вычеркнут в ожидании разъяснений Open Group и с учетом того, что это делается неправильно в некоторых реализациях)


¹ head , встроенный в ksh93 (включен если вы поместите / opt / ast / bin перед $ PATH ), для сокетов (тип файлов без поиска) вместо заглянет на вход ( используя recvfrom (..., MSG_PEEK) ) до фактического чтения , чтобы увидеть, сколько ему нужно прочитать, чтобы убедиться, что он не читает слишком много. И возвращается к чтению по одному байту для других типов файлов. Это немного более эффективно, и я считаю, что это основная причина, по которой он реализует свои каналы с помощью socketpair () s вместо pipe () . Обратите внимание, что это не совсем защита от дурака, поскольку существует состояние гонки, которое может быть запущено, если другой процесс читает из сокета между peek и read .

7
27.01.2020, 20:18

Теги

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