ディレクトリ内のファイルをカウントするためにwcにパイプするより簡潔な代替手段はありますか


12

もしそうならls -1 target_dir | wc -l、ディレクトリ内のファイルの数を取得します。これは少し面倒です。もっとエレガントで簡潔な方法はありますか?


2
wcにパイピングするときに「-1」は必要ありません。
スティーブ

lsすでに合計数を示しているので、どうls -l | head -1ですか?短いものが必要な場合は、エイリアスにします。
ダニエルワーグナー

2
@DanielWagnerによって出力される「total:nnn」ls -lは、ファイルの数ではなく、ファイルの合計サイズを示します。
デビッドリチャービー14年

2
ことを忘れないでくださいls | wc -l任意のファイル名が改行を含んでいる場合、あなたに間違ったカウントを与えるだろう。
chepner 14年

これはファイルシステムに依存し、ディレクトリ内のディレクトリ+ 2をカウントします。答えには2つ余分があります(それ自体とその親をカウントするため)。 stat -c %h .同じ情報提供しますls -ld . | cut -d" " -f 2
Ctrl + Alt + delor

回答:


12

bash 4+(Ubuntuのサポートされているバージョンがある)を想定:

num_files() (
    shopt -s nullglob
    cd -P -- "${1-.}" || return
    set -- *
    echo "$#"
)

として呼び出しnum_files [dir]ます。dirオプションです。それ以外の場合は、現在のディレクトリを使用します。元のバージョンでは隠しファイルはカウントされないため、これもカウントされません。あなたがそれを望むなら、shopt -s dotglob前にset -- *

元の例では、通常のファイルだけでなく、ディレクトリやその他のデバイスもカウントします。通常のファイル(通常のファイルへのシンボリックリンクを含む)のみが必要な場合は、それらを確認する必要があります。

num_files() (
    local count=0

    shopt -s nullglob
    cd -P -- "${1-.}" || return
    for file in *; do
        [[ -f $file ]] && let count++
    done
    echo "$count"
)

GNU findがある場合、次のようなオプションもあります(これには、元のコマンドでは実行されなかった隠しファイルが含まれます)。

num_files() {
    find "${1-.}" -maxdepth 1 -type f -printf x | wc -c
}

(通常のファイルへのシンボリックリンクもカウントしたい場合に変更-type-xtypeます)。


set非常に多くのファイルがある場合、失敗しませんか?xargs一般的な場合にそれを機能させるには、いくつかの加算コードを使用する必要があると思います。
l0b0

1
またshopt -s dotglob、ファイルの.カウントを開始したい場合
デジタルトラウマ

1
@ l0b0 setこれらの状況では失敗することはないと思います。なぜなら実際にを実行していないからですexec。ウィットに、私のシステムで、getconf ARG_MAX262144を生成するが、私がしなければtest_arg_max() { set -- {1..262145}; echo $#; }; test_arg_max、それは喜んで262145.返信
小次郎

@DavidRicherby -maxdepthはPOSIXではありません。
クリスダウン

4
@MichaelMartinez明らかなコードを書くことは、正しいコードを書くことに代わるものではありません。
クリスダウン

3

f=(target_dir/*);echo ${#f[*]}

名前にスペース、改行などが含まれるファイルに対して正常に動作します。


コンテキストを提供できますか?これはbashスクリプトに入れるべきですか?
codecowboy 14年

出来た。シェルに直接置くこともできます。そのバージョンは、現在のディレクトリが必要だと想定していました。あなたの質問に近くなるように編集しました。基本的には、ディレクトリ内のすべてのファイルを含むシェル配列変数を作成し、その配列のカウントを出力します。配列を持つシェル(bash、ksh、zshなど)で動作するはずですが、おそらく単純なsh / ash / dashではありません。
アーロンデイヴィス

2

ls端末に直接出力する場合のみ複数列です。「-1」オプションを削除できます。wc「-l」オプションを削除できます。最初の値のみを読み取ります(遅延ソリューション、法的証拠には使用されません、犯罪捜査、ミッションクリティカル、戦術的操作..)。

ls target | wc 

5
これは、改行を含むファイル名では失敗します。
l0b0

@Emmanuel wc些細な場合でもファイルの数を取得するには、あなたの結果を解析する必要があります。
l0b0 14年

@Emmanuelこれがtarget展開されると、ハイフンで始まるものが含まれるグロブの場合、これは失敗します。たとえば、新しいディレクトリを作成し、そのディレクトリに移動して実行しますtouch -- {1,2,3,-a}.txt && ls *|wc(NB:rm -- *.txtこれらのファイルを削除するために使用します)
デビッドリチャービー

という意味wc -lですか?それ以外の場合は、ls出力の改行、単語、およびバイトカウントを取得します。それはデビッド・リチャービーが言ったことです:あなたは再びそれを解析しなければなりません。
エリック14年

@erik wc引数なしで、最初の引数が改行であることを脳が知っている場合、解析する必要はありません。
エマニュエル

2

(名前に改行が含まれるファイルを処理するときの正確さよりも)目的の簡潔さが必要な場合は、単に「行カウント」にエイリアスwc -lすることをお勧めしlcます。

$ alias lc='wc -l'
$ ls target_dir|lc

他の人が指摘したように、パイプへの書き込みは自動的に行われるため、-1オプションは必要ありません。(常に列モードを使用するようにエイリアスを設定している場合を除きます。以前も見ましたが、あまり頻繁ではありません。)lslsls

lcエイリアスは、一般的には非常に便利で、あなたが「カレントディレクトリを数える」ケースを見れば、この質問に対して、ls|lcあなたが得ることができるように簡潔としてについてです。


2

これまでのところ、アーロンはあなた自身よりも簡潔な唯一のアプローチです。アプローチのより適切なバージョンは次のようになります。

ls -aR1q | grep -Ecv '^\./|/$|^$'

これは、ディレクトリではなく、すべてのファイルを再帰的に一覧表示します。現在のディレクトリの下の.dotfilesを含む行ごとに1つ、非印刷文字を置き換えるために必要に応じてシェルグロブを使用します。grepは、親ディレクトリのリストまたは..または* /または空白行をフィルターで除外します。したがって、ファイルごとに1行しかないはずです-grepが返す合計数。子ディレクトリも含めたい場合:

ls -aR1q | grep -Ecv '^\.{1,2}/|^$'

-R再帰的な結果が必要ない場合は、どちらの場合でも削除します。


1
私はそのようなことをすることを好む傾向がありfindます。カウントのみが必要な場合は、これが機能するはずですfind -mindepth 1 -maxdepth 1 -printf '\n'|wc -l(深さコントロールを削除して、再帰的な結果を取得します)。
アーロンデイヴィス

@AaronDavies-それは実際には機能しません。これらのファイル名のいずれかに改行を入れて、自分で確認してください。また、同じことを移植可能にするには、次のようにします。- find . \! -name . -prune | wc -lもちろん、まだ機能しません。
mikeserv

1
私は従いません- printf命令はファイル名をまったく含まない定数文字列(改行)を出力するため、結果は奇妙なファイル名とは無関係です。もちろん、このトリックはfindサポートされていない場合は実行できませんprintf
アーロンデイヴィス

@AaronDavies-ああ、本当。ファイル名が含まれていると仮定しました。もちろん、移植性のある方法で行うことができます:find .//. \!. -name . -prune | grep -c '^\.//\.'
mikeserv

鮮やかさ!/ファイル名に表示できない他の唯一の文字であるため、.//.シーケンスはすべてのファイルに対して正確に1回表示されることが保証されています。しかし、いくつかの質問-なぜ.//.、そしてなぜ-pruneですか?これはいつ異なるのでしょうfind . \! -name . | grep -c '^\.'か?(私は.あなた\!.のタイプミスであると仮定します。)
アーロンデイヴィス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.