無邪気な努力をしています。
$ 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
次のようにファイルを1つずつ処理できます(これにより、メモリ消費量が減り、ストリーミングメカニズムに近づきます)。
$ 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
?これらの一般的な操作のために小さなシェルスクリプトを書くのは厄介です。
答え1
少なくともBashでは動作する簡単な修正です。printf
組み込みであり、コマンドライン引数制限が適用されないためです。
printf "%s\0" * | xargs -0 cat | sort -u > /tmp/bla.txt
(echo * | xargs
スペースなどを含むファイル名を処理する以外は機能します。)
答え2
GNUsort
と組み込みシェルの使用printf
(現在、いくつかのバリエーションを除くすべてのPOSIX様シェルpdksh
):
printf '%s\0' * | sort -u --files0-from=- > output
1つの問題は、このパイプラインの2つのコンポーネントが同時に独立して実行されるため、左側のコンポーネントがglobを拡張したときに*
右側のコンポーネントがすでにoutput
ファイルを作成している可能性があることです-u
。output
入力ファイルは出力ファイルなので、出力を別のディレクトリ(> ../output
例:)に移動するか、globが出力ファイルと一致しないことを確認する必要があります。
この場合、問題を解決する別の方法は、次のように書くことです。
printf '%s\0' * | sort -u --files0-from=- -o output
これは書き込み用にsort
開きますがoutput
(私のテストでは)ファイル全体のリストを受け取るまで(グローブが拡張されてから長い時間が経過してから)機能しません。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
レベルの一意の行ではなく、そのアルゴリズムでソートされた各行セットの1つを報告します。バイトレベルで一意の行だけに興味があり、ソート順序についてはあまり気にしない場合は、ソートがバイト値に基づいて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数。