如何使用wc和管道来查找某个目录下有多少个文件和目录?

如何使用wc和管道来查找某个目录下有多少个文件和目录?

如何使用字计数器 ( wc) 和管道来计算/usr/bin目录中有多少个文件或目录?

答案1

一种方法是使用ls为我们提供文件列表,但我们希望保证该列表每行仅显示 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因为它显示什么是目录,什么是 aa 文件。

例子

$ 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'

(同样,隐藏文件不包括在内。请注意,目录和常规文件是两种类型的文件。还有更多类型的文件,例如命名管道、符号链接、设备、套接字...)。

递归

如果您需要递归地查找文件和目录,/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将包含换行符的目录和文件计为 2 项,而不是 1 项。

$ ls -1 | wc -l
10

如果使用 GNU 实现,解决此问题的一种方法find是利用 的find功能来打印其他内容来代替它找到的每个文件,然后对这些文件进行计数。

例子

$ find . -printf . | wc -c
9

在这里,我们找到当前目录中的所有内容(除了..),并为每个内容打印一个点(.),然后使用 的计算字节wc而不是行的能力来计算点的数量wc -c

参考

答案2

如果您想使用 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无法确定类型的文件的符号链接,因为该文件不存在,或者位于您无权访问的目录中,或者文件路径解析中存在循环就我而言,这两个符号链接现在已经消失了)。

这些都不算...。如果您希望将它们包括在内(为什么要这样做?),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

这些是同一个文件(索引节点为 672252 的文件)的 3 个目录条目(又名文件名,又称为硬链接)。使用 GNUfind和 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

答案3

您还没有说您是否想要递归地 /usr/bin 下的所有文件或仅在第一级下。另外,你如何获得你正在数的单词?通常的查找方法是在 wc 中运行 find。像这样:找到 /usr/bin | wc -l Find 将列出那里的所有内容、目录和文件。 Wc -l 将计算 find 输出中的所有行。这是课堂作业吗?如果是的话也没关系,但我想知道你为什么需要这些信息,以便我可以更仔细地调整响应。如果您需要更多,请告诉我。科斯塔

答案4

在 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

相关内容