web-dev-qa-db-ja.com

sortコマンドはデータを自由に追加/削除します

私はsortコマンドを使用して、これからダウンロードしたrockyou.txtワードリストをソートします site

% sort rockyou.txt > rockyou_sorted.txt

ただし、両方のファイルのファイルサイズを確認すると、サイズが異なりますtheソートされたファイルの方が小さい

% du -shk rockyou_sorted.txt rockyou.txt 
147520  rockyou_sorted.txt
148304  rockyou.txt

興味深いのは、- ここ からダウンロードしたrockyou.txtワードリストのクリーンバージョンで同じ手順を繰り返すと、反対の結果、つまりがソートされるということですファイルが大きい

% sort rockyou_cleaned.txt > rockyou_cleaned_sorted.txt
% du -shk rockyou_cleaned_sorted.txt rockyou_cleaned.txt 
114752  rockyou_cleaned_sorted.txt
102104  rockyou_cleaned.txt

なんでそれ?誰かが説明してくれませんか?私は何か間違ったことをしていますか?ソートされたファイルと元のファイルの両方が同じサイズである必要があると思いますか?

UPDATE 1、以下のFrancescoLucianòのコメントに従って:-oパラメータを指定したこのsortコマンドの使用

% sort rockyou.txt -o rockyou_sorted_sO.txt
% du -shk rockyou_sorted_sO.txt rockyou.txt
147996 /Users/Martin/Downloads/rockyou_sorted_sO.txt
148304 /Users/Martin/Downloads/rockyou.txt

ソートされたファイルは元のファイルよりも小さいですが、上記のsortコマンドのバージョンを使用していたときほどではありません。

行数はすべてのファイルで同じです。

% wc -l rockyou_sorted_sO.txt rockyou_sorted.txt rockyou.txt
14344391 rockyou_sorted_sO.txt
14344391 rockyou_sorted.txt
14344391 rockyou.txt
43033173 total 

更新2、以下のbey0ndのコメントに従って:set | grep LANGは何も出力しません。

% set | grep LANG
%

% chardet rockyou* 
zsh: command not found: chardet
% uchardet rockyou*
rockyou.txt: UTF-8
rockyou_sorted.txt: UTF-8
rockyou_sorted_duplicut.txt: UTF-8
rockyou_sorted_sO.txt: UTF-8

UPDATE 3、steeldriverのコメントに従って:

% system_profiler SPSoftwareDataType
Software:

    System Software Overview:

      System Version: macOS 10.15.4 (19E287)
      Kernel Version: Darwin 19.4.0
      Boot Volume: Macintosh HD
      Boot Mode: Normal
      Computer Name: *REDACTED* MacBook Pro
      User Name: *REDACTED*
      Secure Virtual Memory: Enabled
      System Integrity Protection: Enabled
      Time since boot: 6 days 4:57

ファイルシステムはAPFSです。

UPDATE 4、以下のroaimaのコメントに従って:

% ls -l rockyou*
-rw-r--r--@ 1 **REDACTED**  staff  139921497 May 16 12:24 rockyou.txt
-rw-r--r--  1 **REDACTED**  staff  139921847 May 16 12:25 rockyou_sorted.txt
-rw-r--r--  1 **REDACTED**  staff  139919642 May 16 12:29 rockyou_sorted_duplicut.txt
-rw-r--r--  1 **REDACTED**  staff  139921847 May 16 13:19 rockyou_sorted_sO.txt

% stat -f .
.

更新5、以下のアイザックのコメントに従って:

% head -n3 rockyou.txt | od -An -tcx1 
           1   2   3   4   5   6  \n   1   2   3   4   5  \n   1   2   3
           31  32  33  34  35  36  0a  31  32  33  34  35  0a  31  32  33
           4   5   6   7   8   9  \n                                    
           34  35  36  37  38  39  0a 

% LC_ALL=C sort rockyou.txt >rockyou_sorted_with_LC.txt
% du -shk rockyou_sorted_with_LC.txt rockyou.txt
147520  rockyou_sorted_with_LC.txt
140476  rockyou.txt
% wc -l rockyou_sorted_with_LC.txt rockyou.txt
 14344391 rockyou_sorted_with_LC.txt
 14344391 rockyou.txt
 28688782 total

UPDATE 6、以下のfra-sanのコメントに従って:

% sort --version
2.3-Apple (101.40.1)
% locale        
LANG=""
LC_COLLATE="en_US.UTF-8"
LC_CTYPE="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_ALL="en_US.UTF-8"
6
yssup

ここでは2つのことが起こり、それらは互いに相反して機能します。

  1. 入力ファイルは一貫してエンコードされておらず、sortによって有効なUTF-8に変換されます。これにより、ファイルがbiggerになります。これは、ls -l- reportedサイズに影響します。
  2. ファイルシステムストレージでは、奇妙なことが発生します。これは、同じサイズのファイルで使用されるブロックの数が、ファイルの作成方法によって異なります。これは、du -shk- reportedのサイズに影響し、ほとんどの場合smallerになります(ただし、どちらの方法でもかまいません)。

最初のポイントについて2番目よりも正確に説明できますが、duは、特にAPFSで個々のファイルサイズを測定するための適切なツールではないということです。

次の2つのセクションでは、両方の要素の雑草について詳しく説明します。


要因(1)の場合、ファイルにはUTF-8エンコードされていない行が含まれています。これはmacOSのデフォルトのロケールエンコードです。 sortコマンドは、これらの正しくエンコードされていない行を出力時に変更し、ファイルを大きくします。これについては以下で詳しく調査しますが、これは簡単な答えです。それで十分であれば、次のセクションにスキップできます。

提供されたファイルをCロケールで並べ替えてから、en_US.UTF-8ロケールで並べ替えると、2つのファイルの実際のサイズが異なります。

139921497 rockyou.txt
139921497 rockyou_c.txt
139921847 rockyou_sorted.txt

CでソートされたファイルとUTF-8でソートされたファイルの最初の違いは

299c299
<  �R3CKL3$$�
---
>  R3CKL3$$

最初の行には、パスワードの最初と最後にバイト0x93と0x94が含まれていますが、これらはUTF-8では有効なスタンドアロンバイトではありません(マルチバイト文字の継続バイトとしてのみ表示できます)。 2番目には、UnicodeコードポイントU + 0093およびU + 0094が含まれ、それぞれ2バイトのUTF-8、C2 93およびC2 94としてエンコードされます。

その結果、元の10バイトの行が12バイトの行として書き出されます。ファイル全体で、これらの変更により、元のファイルよりもソートされたファイルに最大350バイト追加されます。

ここで起こったと私が信じているのは:

  1. 元の行は“R3CKL3$$”(引用符を含む)で、 Windows-1252コードページ (cp1252)でエンコードされていました。ペアの引用符は、そのエンコーディングでは0x93と0x94です。
  2. 他の多くのエントリと同様に、エンコーディングを考慮せずに、このコレクションに未加工のバイトとして追加されました。
  3. 真のLatin-1 ISO 8859-1では、バイト範囲0x80-0x9fは使用されていませんが、ISO-8859-1(追加のハイフンに注意)では C1制御文字 で埋められます。
  4. ISO-8859-1はすべてUnicodeのブロック " Latin-1 Supplement "としてエンコードされ、コードポイントは未加工のバイト値に対応し、マルチバイトエンコーディングC2 80C2 BFおよびC3 80C3 BFで表されます。 TF-8 で。
  5. macOS sortは、単一の継続バイトを試行されたISO-8859-1として解釈し、それらを内部的にUnicode文字列に変換してソートします。バイト0x93はU +になります。ソートされる文字列の0093。
  6. これらの翻訳された文字列は、ファイルの元の行ではなく、UTF-8で出力されます。

サイトの他の質問では、必要に応じて、事実の後に misencoded cp1252 file を修正する方法について説明しています。

POSIXが注記 ロケールで有効な文字を形成しないバイトシーケンスが行に含まれている場合、ユーティリティの動作は定義されていないため、これは、 standardであり、適合バグではありません。それはまだ少なくとも予期せぬことであり、間違いなく行動上のバグです。私が試した他の種類の実装は、このように動作しません。

この要因により、ファイルをソートするとわずかに大きくなり、本当に大きくなる-ファイルから読み取ると、より多くのバイトが取得されます。


要因(2)は、全体としてファイルが「小さくなる」ことを要求しますが、それは幻想のようなものです。 duがサイズが異なると言っているからといって、ファイルを読み取っても必ずしもバイト数が増減するわけではありません。

du -shkは一般に、ファイルサイズをチェックする適切な方法ではありません。

Duユーティリティは、各ファイル引数のファイルシステムブロック使用状況を表示します

つまり、論理サイズではなく、ファイルが占める物理スペースの量に関する情報を報告します。ファイルシステムと問題のファイルの正確なパラメーターに応じて、ブロック数は予想とはかなり異なる場合があります。ファイルをデバイス全体に圧縮する場合など、通常はそうではない場合など、ブロック数が役立つケースがあります

現代のファイルシステムは常に与えられたとおりにデータを正確に書き込むとは限らない:たとえば、ブロックカウントが今日あまり役に立たない理由の1つ:たとえば、前にサイレントで圧縮する可能性があるより多くまたはより少ない範囲でそれを格納し、必要なブロックを少なくするか、ブロック内に空のスペースを残して、より多くのブロックを使用して将来の挿入を容易にします。スパースファイルはゼロのブロックを省略しますが、重複排除はそれよりもさらに進む可能性があります。

APFSの場合、いくつかのアルゴリズム、一部の重複排除とデルタエンコーディング、暗号化、高度なメタデータを使用して圧縮をサポートします。これらの一部またはすべてが機能している可能性があります。アプリケーションの実装とシステムの負荷に応じて、ファイルが書き込まれるときの透過圧縮の変動の可能性が最も高いです。

数回ファイルをcatするだけで、すでに違いがわかります。 rockyou.txtcurl -Oをダウンロードした場合:

  • cat rockyou.txt > rockyou2.txtは、同じバイトカウント(139921497)でブロックカウントが異なるファイルを作成します(curl- createdの147504とcat 'sの147460)
  • 新しいファイルをキャッチすると、cp(150512)と同様に、もう一度別のブロック数(147520)が得られます。
  • 両方の行を再度実行すると、最初の試行とは異なる結果が得られます。

それがなぜなのか正確にはわかりませんし、それを伝えるための合理的な方法があるのか​​わかりません。他のデータよりもデータを圧縮するのに苦労したことがあります。すべての場合において、ファイルは実際には同じサイズであり、どのバージョンから読み取っても同じバイトが返されます。 APFSやその他の最新の高性能ファイルシステムで報告されたブロック数からは、あまり有用な情報が得られません。ファイルをデバイスに圧縮している場合は、最小バージョンを取得するために数回試行することが役立つ場合がありますが、それ以外の場合は検討する価値がありません。


全体的に、エンコード方式の問題があり、ファイルが本当にわずかに大きくなりファイルシステムの動作により、より大きなファイルのblock countが報告され、テストではファイルが小さくなります。真のサイズ測定は、ソート時に350バイトの一貫した増加を示しています。見方によっては、これはソートのバグかもしれませんし、useのソートにバグがあり、悪いファイルを与えているかもしれません。

4
Michael Homer