Вопрос или проблема
Философия UNIX гласит: делай одну вещь и делай ее хорошо. Создавайте программы, которые обрабатывают текст, потому что это универсальный интерфейс.
Команда sort
, по крайней мере GNU sort, имеет опцию -o
, чтобы выводить в файл вместо stdout
. Зачем, скажем, sort foobar -o whatever
, когда я могу просто sort foobar > whatever
?
Это не только GNU sort, так же и BSD sort имеет это. А почему?
(Я тоже думал, что это хороший вопрос…)
Из руководства:
“Аргумент указывает имя выходного файла, который будет использоваться
вместо стандартного вывода. Этот файл может быть таким же, как один
из входных файлов.”
Нельзя перенаправить в тот же файл, так как перенаправление стирает файл.
Чтобы прояснить, если я хочу отсортировать файл и поместить отсортированные результаты в то же место, я могу попробовать sort < foo > foo
. Однако перенаправление вывода обрезает файл foo
в подготовке к получению вывода. И тогда нечего сортировать. Без параметра “-o” это можно было бы сделать так: sort < foo > bar ; mv bar foo
. Я допускаю, что опция -o
делает что-то подобное, чтобы вам не пришлось об этом беспокоиться.
Опция ‘-o’ уже была в sort
из Шестого издания Unix
Однако я согласен с вами, что это не соответствует философии Unix. uniq
не имел этой опции (и sort
не имел -u
тогда).
На моем PDP-11 я использовал небольшую программу, которая принимала один параметр:
renac whatever
Если whatever
уже существовал, программа записывала бы все из stdin во временный файл, который переименовывался в whatever
только после того, как ввод из stdin заканчивался. Таким образом, можно было бы перенаправлять вывод любой команды в renac
вместо перенаправления в имя файла, исключая вероятность перезаписи входных данных. Решение проблемы перезаписи таким образом, на мой взгляд, более соответствует философии Unix.
Позднее в программу были добавлены возможности: не перезаписывать файл вывода, если на stdin ничего не поступило (например, из-за ошибки при наборе команды), и добавление опции для добавления stdin в указанный файл.
Это была одна из первых (если не первая) настоящих программ на C, которые я написал (для работы я в основном программировал на Паскале на этой системе).
В худшем случае sort file >newfile && mv newfile file
может использовать в три раза больше места на диске, чем данные в file
. С sort -o file file
в худшем случае данные должны храниться на диске только один дополнительный раз.
Когда у вас данных больше, чем может поместиться в памяти, sort
сортирует данные партиями, сохраняя отсортированные блоки входных данных во временной директории. Когда все блоки отсортированы по отдельности, утилита объединяет отсортированные блоки и выводит результат.
С -o
утилита может записывать результат в тот же файл, из которого поступали входные данные (либо из памяти, если данные небольшие, либо из операций слияния предвариательно отсортированных блоков). Это позволяет избежать одновременного хранения на диске отсортированного окончательного вывода и неотсортированных данных.
.
Ответ или решение
Теория
В мире UNIX-философии, одна из основных заповедей заключается в том, чтобы программы выполняли одну задачу, но выполняли её хорошо. Это подход к разработке программного обеспечения, который ставит простоту и удобство в центр внимания. Одной из таких утилит является команда sort
, широко используемая для сортировки строк текстовых файлов. Команда sort
предлагает ряд опций, одна из которых — это -o
, служащая для вывода результатов сортировки в указанный файл, а не в стандартный вывод (stdout
).
Вопрос, который часто возникает: "Почему использование sort foobar -o whatever
более полезно, нежели sort foobar > whatever
?" Ответ на этот вопрос кроется в механизмах работы с файлами в UNIX-системах и особенностях обработки данных.
Пример
Рассмотрим пример: у нас есть текстовый файл foo
, который нужно отсортировать и сохранить результат обратно в тот же файл. Интуитивно, используя перенаправление, можно попробовать выполнить команду sort < foo > foo
. Однако, эта команда не будет работать как ожидается, поскольку при перенаправлении > foo
файл foo
будет немедленно обнулен для записи результата, тем самым стирая все данные до того, как sort
успеет их прочитать. В результате, для использования перенаправления, необходимо прибегнуть к обходному пути:
sort foo > bar
mv bar foo
В этом сценарии мы создаем промежуточный файл bar
, что требует дополнительных затрат на дисковое пространство и времени на выполнение команды mv
.
Применение
Вот здесь и проявляется полезность опции -o
в команде sort
. При использовании sort -o foo foo
, утилита sort
сохраняет результат напрямую в тот же файл, из которого читает данные. Это позволяет избежать создания промежуточных файлов и решает проблему перезаписи исходного файла до завершения сортировки. Плюсы такого подхода очевидны:
-
Эффективное использование дискового пространства: С
sort -o
содержимое исходного файла заменяется отсортированным результатом без необходимости в дополнительных файлах. Это особенно важно при работе с большими объемами данных, когда возможность мешать исходные и отсортированные данные становится критичной. -
Оптимизация времени выполнения: Убирается этап лишнего перемещения данных, что сокращает общее время выполнения операции.
-
Удобство и простота: Требуется меньше команд, что снижает вероятность ошибок и упрощает читаемость скриптов.
Таким образом, возможность записывать результат сортировки в тот же файл, который используется в качестве ввода, делает sort -o
незаменимым инструментом в арсенале пользователя UNIX-систем. Это пример того, как понимание специфики работы утилит и механизмов управления файлами UNIX помогает в повседневных задачах оптимизировать процессы и повысить производительность работы.