Avec GNU sort
, et un shell où printf
est intégré (tous ceux de type POSIX de nos jours sauf quelques variantes de pdksh
):
printf '%s\0' * | sort -u --files0-from=- > output
Maintenant, un problème avec cela est que parce que les deux composants de ce pipeline sont exécutés simultanément et indépendamment, au moment où celui de gauche développe le *
glob, le droit peut avoir output
déjà créé le fichier, ce qui pourrait poser problème (peut-être pas avec -u
ici) comme ce output
serait à la fois un fichier d'entrée et de sortie, vous voudrez peut-être que la sortie aille dans un autre répertoire ( > ../output
par exemple), ou assurez-vous que le glob ne correspond pas au fichier de sortie.
Une autre façon de le résoudre dans ce cas est de l'écrire:
printf '%s\0' * | sort -u --files0-from=- -o output
De cette façon, il sort
s'ouvre output
pour l'écriture et (dans mes tests), il ne le fera pas avant d'avoir reçu la liste complète des fichiers (tant de temps après que le glob ait été développé). Cela évitera également de vous encombrer output
si aucun des fichiers d'entrée n'est lisible.
Une autre façon de l'écrire avec zsh
oubash
sort -u --files0-from=<(printf '%s\0' *) -o output
Cela utilise la substitution de processus (où <(...)
est remplacé par un chemin de fichier qui se réfère à la fin de lecture du canal d' printf
écriture). Cette fonctionnalité vient de ksh
, mais ksh
insiste pour rendre l'expansion d' <(...)
un argument séparé à la commande afin que vous ne puissiez pas l'utiliser avec la --option=<(...)
syntaxe. Cela fonctionnerait cependant avec cette syntaxe:
sort -u --files0-from <(printf '%s\0' *) -o output
Notez que vous verrez une différence avec les approches qui alimentent la sortie de cat
sur les fichiers dans les cas où il y a des fichiers qui ne se terminent pas par un caractère de nouvelle ligne:
$ 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
Notez également que sort
trie en utilisant l'algorithme de classement dans les paramètres régionaux ( strcollate()
), et sort -u
signale une de chaque ensemble de lignes qui trient la même chose par cet algorithme, pas des lignes uniques au niveau de l'octet. Si vous ne vous souciez que des lignes uniques au niveau de l'octet et ne vous souciez pas tellement de l'ordre dans lequel elles sont triées, vous souhaiterez peut-être fixer les paramètres régionaux à C où le tri est basé sur les valeurs d'octets ( memcmp()
; cela accélérerait probablement les choses de manière significative):
printf '%s\0' * | LC_ALL=C sort -u --files0-from=- -o output
sort
le fait automatiquement pour plusieurs entrées de fichiers .. maissort -u *
échoueraitArgument list too long
aussi avec je suppose