С GNU sort
и printf
встроенной оболочкой (в настоящее время все POSIX-подобные, кроме некоторых вариантов pdksh
):
printf '%s\0' * | sort -u --files0-from=- > output
Теперь проблема в том, что, поскольку два компонента этого конвейера запускаются одновременно и независимо, к тому времени, когда левый расширяет *
глобус, правый может уже создать output
файл, который может вызвать проблемы (возможно, не -u
здесь) Как output
и входной, и выходной файл, вы можете захотеть, чтобы выходные данные перешли в другой каталог ( > ../output
например), или убедитесь, что глобус не соответствует выходному файлу.
Другой способ решения этой проблемы в этом случае - написать:
printf '%s\0' * | sort -u --files0-from=- -o output
Таким образом, он sort
открывается output
для записи и (в моих тестах) не будет делать этого, пока не получит полный список файлов (так долго после того, как глобус будет расширен). Это также позволит избежать дублирования, output
если ни один из входных файлов не будет читаемым.
Другой способ написать это с помощью zsh
илиbash
sort -u --files0-from=<(printf '%s\0' *) -o output
При этом используется подстановка процесса (где <(...)
заменяется путь к файлу, который относится к концу чтения канала, в который printf
производится запись). Эта функция взята ksh
, но ksh
требует расширения <(...)
отдельного аргумента для команды, чтобы вы не могли использовать его с --option=<(...)
синтаксисом. Это будет работать с этим синтаксисом, хотя:
sort -u --files0-from <(printf '%s\0' *) -o output
Обратите внимание, что вы увидите отличие от подходов, которые cat
передают вывод файлов, в тех случаях, когда есть файлы, которые не заканчиваются символом новой строки:
$ printf a > a
$ printf b > b
$ printf '%s\0' a b | sort -u --files0-from=-
a
b
$ printf '%s\0' a b | xargs -r0 cat | sort -u
ab
Также обратите внимание, что sort
сортирует, используя алгоритм сортировки в locale ( strcollate()
), и sort -u
сообщает одну из каждого набора строк, которые сортируются по этому алгоритму, а не уникальные строки на уровне байтов. Если вы заботитесь только об уникальности строк на уровне байтов и не заботитесь о порядке их сортировки, возможно, вы захотите зафиксировать локаль в C, где сортировка основана на значениях байтов ( memcmp()
; это, вероятно, ускорит дела обстоят значительно):
printf '%s\0' * | LC_ALL=C sort -u --files0-from=- -o output
sort
делает это автоматически для ввода нескольких файлов ... но тогдаsort -u *
,Argument list too long
я полагаю, тоже потерпел бы неудачу