すべてのサブディレクトリのすべてのファイルをソートしたいと思います。 256個のディレクトリに65536個のファイルがあり、各ファイルには1行に1語が含まれ、各ファイルには重複エントリが含まれています。
私が望むのは、-uオプションを使用してこれらの項目をソートすることです(理由はわかりませんが、ソートをuniq -uコマンドに渡すと、実際に重複した一意の行が削除されるのに奇妙ですが、とにかく)。これにより、どの出力ファイルも望ましくありません。メモリ内のファイルを並べ替えて読み込み、上書きしたいと思います。 -o オプションを試しましたが、ファイル名が必要です。
これを再帰的に実行する方法はありますか?
ありがとうございます:)
答え1
それは次のようになります:
find . -type f -size +1c -exec sort -uo {} {} ';'
(2バイト未満のファイルはここからスキップされます。2つの別々の行を作成するには、少なくとも3バイトが必要な場合、または空白行と無制限の行1が続く"\nx"
2バイトが必要になる可能性があるため)。
デフォルトのソート順序は、sort
ロケールのデータソートアルゴリズムに基づいています。
2行は、バイト単位が同じでなくても同じように並べ替えることができます。特に、行に有効な文字を形成しないバイトシーケンスが含まれており、GNUシステム(Debianなど)では、ソート順序が同じでない場合はさらにそうです。文字に対しても同じように定義されているようにソートされます。
あなたはできます:
LC_ALL=C find . -type f -exec sort -uo {} {} ';'
対照的に、ASCIIベースのシステム(たとえば、すべてのアーキテクチャとカーネルのDebian)では、Cロケールの照合はロケールソート順序ではなくバイト値に基づいています(またはIOW、Cロケールの照合はバイト値に基づいています) 。 )行は並べ替えられ、バイトが異なる2つの行が等しく並べられないようにする必要があります。
sort
これはファイルごとに1つの呼び出しを実行します。ファイルが非常に短い場合は、作業を高速化するために次のことを行うことができますzsh
。
zmodload zsh/mapfile
for f (**/*(N.)) print -rC1 -v 'mapfile[$f]' - ${(fou)mapfile[$file]}
sort
これにより、外部コマンドが複数回実行されるのを防ぎ、代わりにo
パラメータu
拡張フラグを使用して行を並べ替えて一意に並べ替えます。入力から空白行(存在する場合)を削除し、隠しファイルをスキップします(D
必要に応じてglob修飾子を追加します)。
GNUとは異なり、sort -u
バイトzsh
単位で等しくない2つの文字列は重複と見なされないため(同じ順序であっても)ロケールをCに変更する必要はありません。
$ロケールヘッダー文字マップ 英国式英語環境 UTF-8 $a=(
答え2
$ find . -type f -exec perl -MList::MoreUtils=uniq -i -0 -n -e \
'print join("\n", uniq split /\n/), "\n"' {} +
これは、内部編集オプションを使用してfind
ファイル名をスクリプトに渡すために使用されます。perl
-i
リスト::追加ユーティリティuniq
Perlに機能を提供します(Perlにはsort
組み込み機能がありますが、1つはありませんuniq
)。 perlのオプションは-n
各入力レコードを繰り返しますが、デフォルトでは何も印刷しません(つまり、明示的に印刷された内容のみを印刷します)。sed
-n
スクリプトは、-0
各ファイルを一度に飲み込むことができるように、入力レコード区切り文字を対応するオプションを使用してNULに設定します。次に、各入力ファイルを改行文字に分割し、一意のソート順で印刷します。
List::MoreUtils
Debian(およびUbuntu、Mintなど)のパッケージにあり、liblist-moreutils-perl
Fedora、Centos、またはRHELにも同様のパッケージ名があります。他のディストリビューションでもそれをパッケージ化できます。それ以外の場合は、CPANからインストールしてください。
をインストールしたくない場合やインストールできない場合は、List::MoreUtils
連想配列(「ハッシュ」とも呼ばれる)を使用できます。例えば
$ find . -type f -exec perl -i -0 -n -e \
'%uniq = map {$_ => 1} split /\n/;
print join("\n", sort keys %uniq), "\n"' {} +
まず、いくつかのジャンクファイルでこれらのいずれかを実行して、必要に応じて動作することを確認します。および/または-i
標準出力として印刷するオプションなしでテストします。junk
次の内容を含むファイルでテストしました。
6
5
5
4
3
2
1
1
上記のバージョンのいずれかを実行した後、次のものがjunk
含まれます。
1
2
3
4
5
6
逆順にするには、reverse
または関数の前に追加するだけです。例えば。sort
uniq
print join("\n", reverse sort keys %uniq),"\n"
またはあなたが持っているならスポンジJoey Hessのインストールでは、および以下をmoreutils
使用できます。find
shell
sort -u
sponge
find . -type f -exec sh -c \
'for f in "$@"; do sort -u "$f" | sponge "$f" ; done' find-sh {} +
これは一度sh
フォークする必要があるため、Perlバージョンよりはるかに遅いです。sort
sponge
それぞれすべての入力ファイルを処理するperl
ために一度(*)だけ分岐するのではなく、入力ファイルを処理します。find
(*) すべてのファイル名がコマンドラインに適合すると仮定します。 Linuxでは、約200万文字に相当します。結合されたすべてのファイル名がこれより長い場合は、Perlを2〜3回(またはそれ以上)分岐する必要があります。
sh
複数回フォークする必要があるフォークにも同じことが当てはまります。ただし、find
sh(またはperl)を数回フォークするコストは、合計をフォークするコストと比較して無視できます。sort
sponge
ファイルごとに1回。代わりに+
withを使用すると時間が節約されます。find ... -exec ... {}
\;