ワードカウンター(wc
)とパイプを使用して、/usr/bin
ディレクトリ内のファイルまたはディレクトリの数をカウントするにはどうすればよいですか?
ワードカウンター(wc
)とパイプを使用して、/usr/bin
ディレクトリ内のファイルまたはディレクトリの数をカウントするにはどうすればよいですか?
回答:
1つの方法は、を使用しls
てファイルのリストを提供することですが、このリストでは、1行に1つのファイルまたはディレクトリのみが表示されることが保証されます。-1
スイッチは、私たちのためにこれを行います。
$ ls -1
dir1
dir2
dir3
fileA
fileB
fileC
上記のサンプルデータを空のディレクトリに作成します。
$ mkdir dir{1..3}
$ touch file{A..C}
確認してください:
$ ls
dir1 dir2 dir3 fileA fileB fileC
これでカウントに使用wc -l
して、ls -1
出力のファイルまたはディレクトリに対応する行数をカウントできます。
$ ls -1 | wc -l
6
(ただし、隠しファイルは含まれません)
ファイルまたはディレクトリをカウントするには、戦術を少し変更する必要があります。この場合はls -l
、ディレクトリとファイルを示すので使用します。
$ ls -l
total 12
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileC
次に、を使用grep
して、次のようにディレクトリまたはディレクトリ以外を除外できます。
# directories
$ ls -l | grep "^d"
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
# regular files
$ ls -l | grep "^-"
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileC
wc -l
上記を数えるためにもう一度使用してください:
# directories
$ ls -l | grep "^d" | wc -l
3
# regular files
$ ls -l | grep "^-" | wc -l
3
ただし、wc
完全に回避して、grep
の-c
オプションを使用することができます。
$ ls -l | grep -c '^d'
(ここでも、隠しファイルは含まれていません。ディレクトリとレギュラーは2種類のファイルであることに注意してください。名前付きパイプ、シンボリックリンク、デバイス、ソケットなどの多くのファイルがあります。)
ファイルとディレクトリを再帰的に検索する必要がある場合は、/usr/bin
戦術を完全に変更して、という別のツールを使用することをお勧めしますfind
。
$ find /usr/bin | wc -l
4632
(上記/usr/bin
自体はカウントに含まれます)
上記で使用したのと同じ手法を使用ls
して同様のことを行うことができますls
が、一般的には出力を解析するのに適したツールではありません。find
一方、これはこのために作成され、ファイルまたはディレクトリを検索するスイッチを提供します。
# find files
$ find /usr/bin -type f
# find directories
$ find /usr/bin -type d
(この時、そのノートfind
を除いて(隠しファイルを含めている.
と..
))。
改行文字がファイル名やディレクトリ名を作成するときに使用できる正当な文字である理由がわかりません。使用して上記の方法は、だから、wc
とls
心の中でそれとそれらを使用するので、これらと競合しません。
改行を含むディレクトリとファイル名を作成します。
$ mkdir $'dir4\n5'
$ touch $'fileD\nE'
ls
それらを正しく示しています:
$ ls -1
dir1
dir2
dir3
dir4?5
fileA
fileB
fileC
fileD?E
ただしwc
、改行を含むディレクトリとファイルは、1つではなく2つのアイテムとしてカウントされます。
$ ls -1 | wc -l
10
のGNU実装を使用している場合、これを回避する1つの方法find
は、がfind
検出した各ファイルの代わりに何かを出力し、代わりにそれらをカウントする機能を利用することです。
$ find . -printf . | wc -c
9
ここでは、現在のディレクトリ(を除く..
)内のすべてを検索し、.
それぞれにドット()を出力してから、wc
行の代わりにバイトをカウントするの機能を使用してドットをカウントしていますwc -c
。
/usr/bin
はすべて適切にフォーマットされます(スペースも含まれないため、技術的にはも可能ですecho * | wc -w
)が、改行を含むファイル名でこれらすべてが機能しないことに注意してください。
ls -l
またはls -1
単語ではなく、行を数えているb / cを壊します!find
壊れるかもしれませんが、もう一度、私たちは言葉を行を数えていません。
touch $'foo\nbar'
、空のディレクトリ内にコマンドの1つが続く(たとえばls -1 | wc -l
)とすると、1つではなく2つのファイルが報告されますwc
。ls
改行を他の文字に置き換えない限り(そうではないと思いますが、繰り返しますが、今はテストする立場にありません)。
wc -c
期間を数えるときの問題ですか?
GNUを使用してfind
、いくつかのディレクトリで再帰的に各タイプのファイルの数の内訳を取得したい場合は、次のようにします。
find /some/dir/. ! -name . -printf '%y\n' | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
上の/usr/bin
私のシステムで、それが得られます。
3727 regular files
710 symbolic links
に/dev
:
83 block devices
203 character devices
31 directories
426 symbolic links
1 FIFOs
1 Unix domain sockets
シンボリックリンクの場合、それらを指すファイルのタイプとしてではなくカウントする場合はsymbolic links
、次のように変更できます。
find /some/dir/. ! -name . -printf '%Y\n' | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/N/broken symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
これは今私のために与えます/usr/bin
:
1 directories
4434 regular files
2 broken symbolic links
(壊れたシンボリックリンクはfind
、ファイルが存在しないか、アクセスできないディレクトリにあるか、ファイルのパスの解決にループがあるためにタイプを判別できないファイルへのシンボリックリンクです。私の場合、これらの2つは、なくなったファイルへのシンボリックリンクです)。
これらのカウントのなし.
と..
。それらを含めたい場合は(なぜそうするのですか?)、find
すべてのディレクトリに存在すると想定して体系的にカウントする以外に方法はありません。
find /some/dir/. -printf '%y\n' \( -name . -printf 'd\n' -o \
-type d -printf 'd\nd\n' \) | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
それから私に与える/usr/bin
:
2 directories
3727 regular files
710 symbolic links
GNU find
にアクセスできない場合は、最初のものを次のように書き換えることができます。
find /some/dir/. ! -name . \( \
-type f -exec printf '%.0sregular files\n' {} + -o \
-type d -exec printf '%.0sdirectories\n' {} + -o \
-type l -exec printf '%.0ssymbolic links\n' {} + -o \
-type s -exec printf '%.0sUnix domain sockets\n' {} + -o \
-type b -exec printf '%.0sblock devices\n' {} + -o \
-type c -exec printf '%.0scharacter devices\n' {} + -o \
-type p -exec printf '%.0sFIFOs\n' {} + -o \
-exec printf '%.0sothers\n' {} + \) | sort | uniq -c
今、厳密に言えば、ファイルではなくディレクトリエントリをカウントしています。のようなディレクトリには、/usr/bin
通常、同じファイルを指すいくつかのエントリがあります。たとえば、ここでは、私は持っています:
$ ls -lid /usr/bin/{nvi,nview,nex}
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nex
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nvi
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nview
これらは、同じファイル(inode 672252を持つもの)への3つのディレクトリエントリ(別名ファイル名またはハードリンク)です。ディレクトリエントリの代わりにファイルをカウントし、GNU find
およびGNU を使用しますuniq
(無視して.
、..
いずれにしても他のディレクトリへのハードリンクであるファイル)。
find /some/dir/. ! -name . -printf '%y\t%D:%i\n' |
sort -u |
cut -f1 |
uniq -c |
sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/d/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
私では/usr/bin
、それは与える:
3711 regular files
710 symbolic links
/ usr / bin以下のすべてのファイルが再帰的に必要か、または最初のレベルのすぐ下に必要かについては、まだ述べていません。また、あなたが数えている言葉をどのように得るのですか?見つけるための通常の方法は、wcにfindを実行することです。このように:/ usr / binを見つける| wc -l Findはそこにあるすべてのもの、ディレクトリとファイルをリストします。Wc -lは、find出力のすべての行をカウントします。これはクラスの課題ですか?よろしければ問題ありませんが、応答をより注意深く調整できるように、なぜこの情報が必要なのか不思議に思っていました。さらに必要な場合はお知らせください。コスタ
bashでは、外部ツールなし。
cd dir/ || exit; shopt -s nullglob; shopt -s dotglob; count=(*); echo "${#count}"
bashでは、外部ツールと再帰なし。
shopt -s globstar; shopt -s dotglob
for dir in **/*/; do
unset d f
for files in "$dir"*; do
[[ -f $files ]] && ((++f))
[[ -d $files ]] && ((++d))
done;
printf '%s\n' "$dir - files: ${f:-0} - directories: ${d:-0}"
done
.
ず、..
エントリもカウントしないことに注意してください。ファイルと通常のファイルのあいまいさを解消したい場合があります。