我正在尝试一个天真的:
$ cat * | sort -u > /tmp/bla.txt
失败并显示:
-bash: /bin/cat: Argument list too long
因此,为了避免像(创建一个巨大的临时文件)这样愚蠢的解决方案:
$ find . -type f -exec cat {} >> /tmp/unsorted.txt \;
$ cat /tmp/unsorted.txt | sort -u > /tmp/bla.txt
我虽然可以使用以下方法逐个处理文件(这应该减少内存消耗,并且更接近流机制):
$ cat proc.sh
#!/bin/sh
old=/tmp/old.txt
tmp=/tmp/tmp.txt
cat $old "$1" | sort -u > $tmp
mv $tmp $old
接下来是:
$ touch /tmp/old.txt
$ find . -type f -exec /tmp/proc.sh {} \;
是否有一个更简单、更unix风格的替代方案:cat * | sort -u
当文件数量达到时MAX_ARG
?为这样一个常见的任务编写一个小的 shell 脚本感觉很尴尬。
答案1
一个简单的修复,至少在 Bash 中有效,因为它printf
是内置的,并且命令行参数限制不适用于它:
printf "%s\0" * | xargs -0 cat | sort -u > /tmp/bla.txt
(echo * | xargs
也可以工作,除了处理带有空格等的文件名。)
答案2
使用 GNUsort
和内置的 shell printf
(现在除了 的某些变体之外,所有类似 POSIX 的 shell pdksh
):
printf '%s\0' * | sort -u --files0-from=- > output
现在,一个问题是,因为该管道的两个组件是同时且独立运行的,所以当左边的组件扩展 glob 时*
,右边的组件可能已经创建了output
文件,这可能会导致问题(可能不是-u
这里) asoutput
既是输入文件又是输出文件,因此您可能希望将输出转到另一个目录(> ../output
例如),或者确保 glob 与输出文件不匹配。
在这种情况下解决这个问题的另一种方法是这样写:
printf '%s\0' * | sort -u --files0-from=- -o output
这样,它就可以sort
打开output
进行写入(在我的测试中),在收到完整的文件列表之前(在 glob 扩展后很长时间内)它不会执行此操作。output
如果没有一个输入文件可读,它也可以避免破坏。
另一种写法是用zsh
or来写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
使用区域设置 ( ) 中的排序规则算法进行排序strcollate()
,并sort -u
报告按该算法排序的每组行中的一个,而不是字节级别的唯一行。如果您只关心行在字节级别上是唯一的,并且不太关心它们的排序顺序,那么您可能需要将语言环境修复为 C,其中排序基于字节值(memcmp()
;这可能会加快速度情况显着改善):
printf '%s\0' * | LC_ALL=C sort -u --files0-from=- -o output
答案3
find . -maxdepth 1 -type f ! -name ".*" -exec cat {} + | sort -u -o /path/to/sorted.txt
这将连接当前目录中的所有非隐藏常规文件,并将它们的组合内容(同时删除重复行)排序到文件中/path/to/sorted.txt
。
答案4
就像@ilkkachu,但是 cat(1) 是不必要的:
printf "%s\0" * | xargs -0 sort -u
另外,如果数据很长,也许您想使用 sort(1) 选项 - 平行线=氮
什么时候氮是您计算机的 CPU 数量