web-dev-qa-db-ja.com

最適な方法で取得されたディレクトリ内の最初のファイルの名前

通常、私が入力したディレクトリから最初のファイルの名前を表示したい場合:

ls raw/all | head -n 1

しかし、ディレクトリに多くのファイルがあると、長い時間がかかります


たとえば、900 k近くのファイルがあるdirの場合、次の測定値があります。

time ls raw/all | head -n 1 

real    0m17.250s | 0m10.328s | 0m6.334s
user    0m3.224s  | 0m3.884s  | 0m3.192s
sys     0m0.544s  | 0m0.664s  | 0m0.572s

whileすべてのファイルをループするには:

time ls raw/all | wc -l

real    0m6.455s | 0m5.869s  | 0m5.228s
user    0m3.612s | 0m3.468s  | 0m4.072s
sys     0m0.460s | 0m0.784s  | 0m0.624s

効率的方法で最初のファイルの名前をどのように印刷しますか?

1
Daniel

これには注意が必要です。 2つのアプローチ:


アプローチ1; find

_find . -mindepth 1 -print -quit
_

findおよび_-print_ sは最初に見つかったファイルであり、_-quit_ sはすぐに見つかりました。 _-mindepth 1_は、現在のディレクトリの_._ハードリンクとの一致を防ぎます。

通常のファイルのみに関心がある場合は、_-type f_を追加します。

_find . -type f  -print -quit
_

_-mindepth 1_は、ディレクトリである_._が一致しないため、削除できます。


アプローチ2; shstdbuf、およびawk

これは、多すぎるファイルに対して_ARG_MAX_がトリガーされることに注意してください(引数リストが_ARG_MAX_バイトを超えて長くなりすぎます)。その場合は、アプローチ1を使用します

  • ファイル名を出力するための任意のシェルbuilin(例:printfecho
  • シェルのグロビング、_*_、展開を行う(照合順序は、指定されたlsの_LC_COLLATE_のlocaleと同じでなければなりません)
  • _stdbuf -o0_(stdbufには、GNU coreutilsが付属)を使用して、printf/echoのSTDOUTストリームをアンバッファーします
  • パイプ(_|_)最初のレコードを印刷した後、printf/echoのSTDOUTをawkおよびexit
  • awkが終了すると、stdbufprintf)はSIGPIPEを受け取り、強制終了されます
  • printfを使用して、ASCII NUL(_\0_)で区切られたファイル名を取得し、awkのレコード区切り文字として_\0_を使用して、ファイル名が関係している

これらをまとめる:

_stdbuf -o0 printf '%s\0' * | awk 'BEGIN{RS="\0"} {print;  exit}'
_
2
heemayl