web-dev-qa-db-ja.com

ファイルに含まれる行数でファイルを並べ替える

ファイル内の行数を/group/book/four/Wordに、それらを含む行数で並べ替えて一覧表示するにはどうすればよいですか?

ls -lコマンドはそれらを一覧表示しますが、並べ替えは行いません

33
Ken R

次のようなコマンドを使用する必要があります。

find /group/book/four/Word/ -type f -exec wc -l {} + | sort -rn
  • find:希望するパス上のファイルを検索します。再帰的にしたくなく、find実装がそれをサポートしている場合は、-maxdepth 1オプションの直前に-execを追加する必要があります。
  • exec:すべてのファイルに対してwc -lを実行するようにコマンドに指示します。
  • sort -rn:結果を数値の逆順にソートします。大きい方から低い方へ。

(ファイル名に改行文字が含まれていないことを前提としています)。

36
jherran

非再帰的

再帰性が必要ない場合は、おそらく最も単純なバージョンです:

_wc -l /group/book/four/Word/*|sort -n
_

wcは、_-l_の下にあるすべての(ただし非表示の)(_*_)ファイルの行(オプション_/group/book/four/Word/_)をカウントし、sortは(パイプで_|_)を数値で(オプション_-n_)。

再帰的

誰かがこの回答に、コメントを抑制する前に_grep -rlc_について言及しました。確かにgrepは、特に再帰性が必要な場合に最適な選択肢です:

_grep -rc '^' /group/book/four/Word/|tr ':' ' '|sort -n -k2
_

ディレクトリ_-c_内の(grep)_-r_(つまり、行の先頭)に一致する(オプション_'^'_)再帰的に(オプション_/group/book/four/Word/_)行をカウントします。次に、コロンをスペースで置き換える必要があります。 trを使用して、2番目の列(オプション_-n_)で数値順にソートするsortを支援します(オプション_-k2_)。

更新:可能な制限と実際にtrを取り除く方法についてのステファンのコメントを参照してください。

zshの場合:

lines() REPLY=$(wc -l < $REPLY)
print -rC1 /group/book/four/Word/*(.no+lines)

ファイルの行数で応答する新しいsorting関数linesを定義します。また、o+linesグロブ修飾子を使用します。これは、nとともに(数値ソートの場合)、グロブの結果の順序付け方法を定義します。 (.も通常のファイルのみをチェックするために追加されました)。

これは、ファイル名に隠しファイル(.で始まるもの)以外の文字が含まれている可能性があることを想定しておらず、省略されています。必要に応じて、Dグロブ修飾子も追加します。

lines関数の定義は、そのようなことを頻繁に行う場合に役立ちますが、1回限りの場合は、次のように1回で行うこともできます。

print -rC1 /group/book/four/Word/*(.noe['REPLY=$(wc -l < $REPLY)'])

別のシェルから、単に実行します:

zsh -c '
  print -rC1 /group/book/four/Word/*(.noe['\''REPLY=$(wc -l < $REPLY)'\''])'

または、これらのシェルを実際に使用する必要がある場合に、ksh93/bash配列に格納するには:

typeset -a array
eval "
  array=(
    $(
      zsh -c '
        () {
          print -r -- "${(qq)@}"
        } /group/book/four/Word/*(N.noe['\''REPLY=$(wc -l < $REPLY)'\''])'
    )
  )
"

(ここでは、qquationを安全にするために、適切な一重引用符(evalパラメータ展開フラグを使用)を使用しています)。

8

/group/book/four/Wordのサブディレクトリにあるファイルも必要かどうかは指定しません。 jherranの回答のfindソリューションはサブディレクトリに降りてきます。それが必要ない場合は、代わりにシェルを使用してください。

for file in ./*; do [ -f "$file" ] && wc -l "$file"; done | sort -n

ファイル名に改行を含めることができる場合は、次のようなものを使用できます。

for file in ./*; do 
    [ -f "$file" ] && 
        printf "%lu %s\0" "$(wc -l < "$file")" "$file"
done | sort -zn | tr '\0' '\n'

最後に、doをサブディレクトリに降りたい場合は、bash 4以上でこれを使用できます。

shopt -s globstar
for file in ./**/*; do [ -f "$file" ] && wc -l "$file"; done | sort -n

4.3より前のbashのバージョンは、ディレクトリツリーを再帰的に下降するときに、シンボリックリンクをたどっていたことに注意してください(zsh 'sまたはtcsh' s ***/*)。

また、上記のすべてのソリューションは、隠しファイル(.で始まる名前のファイル、それらを含めるにはshopt -s dotglobを使用)を無視し、シンボリックリンクの行数(findアプローチはしません)。

4
terdon

インストールしたい場合 fd Rustで記述された非常に高速なファイルファインダー(インストールする必要があります。とにかくインストールすると便利です)

fd --type=file . | xargs wc -l | sort -n

基本的にfdはファイルをリストし、xargsはファイルのリストをwcに渡します(Wordカウントを表しますが、-lを渡すと行数をカウントします)。最後に、最小行数からsort -n

2
JustGage

@SkippyleGrandGourouによって提供されたソリューションは私にとってはうまくいかなかったので、findを使用した再帰的なソリューションを次に示します。

find <folder> -name "<filter>" -exec wc {} \; | sort

例:

find . -name "*.jsp" -exec wc {} \; | sort
0