wcとpipeを使用して、特定のディレクトリにあるファイルとディレクトリの数を見つける方法は?


10

ワードカウンター(wc)とパイプを使用して、/usr/binディレクトリ内のファイルまたはディレクトリの数をカウントするにはどうすればよいですか?


この宿題?助けを求めるのは問題ありません。もしそうであれば、それを特定してください。
slm

はい、そうですが、私はここに投稿して、Linuxを初めて使い、非常に複雑になる可能性があるため、何かを達成する方法についてのアイデアを得ます。そして、私はこのコマンドですでに上記の質問を解決しています
現金

ls / bin / usr / bin | 並べ替え| uniq | wc-–
現金

np。助けを求めるのはまったく問題ありません!人々にわかるようにラベルを付けてください。Unixの細かい点を学ぼうとしている人々をここで誰もが喜んで助けます。
slm

回答:


13

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を除いて(隠しファイルを含めている...))。

改行?

改行文字がファイル名やディレクトリ名を作成するときに使用できる正当な文字である理由がわかりません。使用して上記の方法は、だから、wcls心の中でそれとそれらを使用するので、これらと競合しません。

改行を含むディレクトリとファイル名を作成します。

$ 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)が、改行を含むファイル名でこれらすべてが機能しないことに注意してください。
evilsoup 2013年

@evilsoup-いいえ、私は信じていません、ls -lまたはls -1単語ではなく、行を数えているb / cを壊します!find壊れるかもしれませんが、もう一度、私たちは言葉を行を数えていません。
slm

つまり、ファイルに改行が含まれている場合、これは(Windowsを使用しているのでテストできないので)機能しなくなります。したがってtouch $'foo\nbar'、空のディレクトリ内にコマンドの1つが続く(たとえばls -1 | wc -l)とすると、1つではなく2つのファイルが報告されますwcls改行を他の文字に置き換えない限り(そうではないと思いますが、繰り返しますが、今はテストする立場にありません)。
evilsoup 2013年

@evilsoup-正しい、改行文字。正当な文字です。ファイル名の場合、メソッドはそれらのタイプのファイル名と正しく競合することができません。
slm

@StephaneChazelas- wc -c期間を数えるときの問題ですか?
slm

5

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

0

/ usr / bin以下のすべてのファイルが再帰的に必要か、または最初のレベルのすぐ下に必要かについては、まだ述べていません。また、あなたが数えている言葉をどのように得るのですか?見つけるための通常の方法は、wcにfindを実行することです。このように:/ usr / binを見つける| wc -l Findはそこにあるすべてのもの、ディレクトリとファイルをリストします。Wc -lは、find出力のすべての行をカウントします。これはクラスの課題ですか?よろしければ問題ありませんが、応答をより注意深く調整できるように、なぜこの情報が必要なのか不思議に思っていました。さらに必要な場合はお知らせください。コスタ


0

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

2番目は、再帰時にシンボリックリンクを追跡し(通常のファイルへのシンボリックリンクを通常のファイルとしてカウントし、dirsへのシンボリックリンクをdirsとしてカウント)、現在のディレクトリ内のファイルとディレクトリをカウントせ.ず、..エントリもカウントしないことに注意してください。ファイルと通常のファイルのあいまいさを解消したい場合があります。
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.