AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / computer / 问题 / 1651475
Accepted
Hot JAMS
Hot JAMS
Asked: 2021-05-26 05:30:43 +0800 CST2021-05-26 05:30:43 +0800 CST 2021-05-26 05:30:43 +0800 CST

bash:计算目录数

  • 772

作为我的 bash 例程的一部分,我试图找到位于目录 $storage 中的子目录数量并将其关联到某个变量,该变量将在同一脚本中使用

number_dirs=$(ls -ld "${storage}"/* | wc -l)
  printf >&2 '%s is the number of the directories... ' "${number_dirs}" ;sleep 0.2
  printf >&2 "Keep calm!\n"

这适用于 2-4K 左右的目录数量,但不适用于大量数量。我怎么能以同样的方式使用 find 命令呢?

bash
  • 3 3 个回答
  • 44 Views

3 个回答

  • Voted
  1. Best Answer
    DuncG
    2021-05-26T05:39:57+08:002021-05-26T05:39:57+08:00

    一个简单的扫描find将是:

    number_dirs=$(find ${storage} -maxdepth 1 -mindepth 1 -type d | wc -l)
    
    • 1
  2. glenn jackman
    2021-05-26T06:08:15+08:002021-05-26T06:08:15+08:00
    # store all the dir names in an array
    dirs=( "${storage}"/*/ )
    
    num_dirs=${#dirs[@]}
    

    glob 模式中的尾部斜杠将结果限制为仅目录。

    • 0
  3. Kamil Maciorowski
    2021-05-26T07:06:23+08:002021-05-26T07:06:23+08:00

    分析

    请注意,您ls -ld "${storage}"/* | wc -l不仅限于目录;即ls也将列出非目录$storage,wc将它们计算在内。考虑"${storage}"/*/(注意尾部斜杠)将列出目录和目录的符号链接,除非没有匹配项。如果不匹配,则该/*/部分将保持原样。研究什么shopt -s failglob和shopt -s nullglob做什么。

    您的命令没有列出更深的子目录,我认为这种行为是您想要的。

    您的命令通常不会列出隐藏目录(名称以点开头)。如果您对它们感兴趣,请研究shopt -s dotglob。

    如果"${storage}"/*/扩展到大量单词,那么您将获得argument list too long. 这是因为ls它是一个需要使用参数数组调用的外部可执行文件,并且this 有一个限制。


    壳牌可以做到这一点

    您可以让 shell 为您计算目录:

    (shopt -s nullglob && set -- "${storage}"/*/ && echo "$#")
    

    set --将所有名称存储为位置参数,然后echo "$#"打印数字。set是内置的,它不应该受到argument list too long. 我特意使用了一个子shell,所以当前shell的位置参数不受影响。我可以使用一个单独的数组(就像其他答案一样),但是有一个潜在的问题。Bash 允许您设置大量的位置参数。一方面它很好,因为您想要计算大量目录。另一方面,参数需要作为字符串存储在内存中,即使您只想要它们的计数。

    请注意,如果您这样做:

    number_dirs=$(shopt -s nullglob && set -- "${storage}"/*/ && echo "$#")
    

    那么$()无论如何,内部都会在子shell中执行,因此您不需要额外的括号。您可以选择在子shell 中使用数组。在任何情况下,子shell都会立即退出echo,内存会尽快释放。但如果你这样做:

    dirs=( "${storage}"/*/ )
    num_dirs=${#dirs[@]}
    

    如果您不这样做,unset dirs那么阵列将成为负担。立即死亡并释放内存的子shell 比您可能忘记取消设置的消耗内存的数组要好。

    一种或另一种方式,所有扩展的单词都需要存储(如果只是暂时在子shell中),然后才能获得它们的计数。出于这个原因,您可能更喜欢find允许wc即时计数。


    或find+wc

    一个基本的解决方案是在另一个答案中,重点是-type d. 这个想法(正确引用):

    find "$storage" -maxdepth 1 -mindepth 1 -type d | wc -l
    

    可能会失败,因为:

    • -maxdepth并且-mindepth不便携;
    • 目录名称可能包含会导致计数错误的换行符wc -l。

    如果您find支持-printf(因此它很可能支持-maxdepthand -mindepth),那么您可以通过打印单个字节并计算它们来解决后一个问题:

    find "$storage" -maxdepth 1 -mindepth 1 -type d -printf a | wc -c
    

    其中a是一个任意的单字节字符。

    一个便携式(但速度稍慢)的解决方案是这样的:

    ( cd -- "$storage"/ && find . -type d ! -name . -prune -exec sh -c '
        for i do printf a; done
    ' find-sh {} + | wc -c )
    

    子shellcd不影响当前shell 的当前工作目录。我首先使用它是因为cd -- "$storage"/它允许我稍后引用它,因此无需修剪即可轻松排除它。如果没有,我将需要使用类似的东西,但随后会解释为一种模式;所以这通常会失败。$storage.cd! -path "$storage"find$storage

    另一方面,如果您被允许r读取目录但不能x执行(cd进入,请参阅此答案),那么cd将不起作用,而没有cd可能的解决方案。


    笔记

    • 在双破折号和尾部斜杠中,使路径类似于cd -- "$storage"/甚至被解释为实际路径名。-foo-

    • find-sh在这里解释:什么是第二个 sh sh -c 'some shell code' sh?.

    • 如果您不想计算隐藏目录,请! -name '.*'在-prune.

    • -type d与目录的符号链接不匹配。为了比较:shell globbing patterns like */do 匹配它们。

    • 如果要下降到子目录并计算整个子树,请省略-prune.

    • shopt不便携。sh我不知道在纯shopt -s nullglobBash中做的事情没有直接的方法。你的问题被标记为bash,所以这应该不是问题。

    • 0

相关问题

  • 在非 root 用户上用 bash 替换 zsh

  • 在 macOS High Sierra 的终端中设置环境变量时遇到问题

  • 对于 cp 或 mv,是否有等同于 cd - 的东西?

  • Notify-发送窗口下出现的通知

  • 如何从 WSL 打开 office 文件

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何减少“vmmem”进程的消耗?

    • 11 个回答
  • Marko Smith

    从 Microsoft Stream 下载视频

    • 4 个回答
  • Marko Smith

    Google Chrome DevTools 无法解析 SourceMap:chrome-extension

    • 6 个回答
  • Marko Smith

    Windows 照片查看器因为内存不足而无法运行?

    • 5 个回答
  • Marko Smith

    支持结束后如何激活 WindowsXP?

    • 6 个回答
  • Marko Smith

    远程桌面间歇性冻结

    • 7 个回答
  • Marko Smith

    子网掩码 /32 是什么意思?

    • 6 个回答
  • Marko Smith

    鼠标指针在 Windows 中按下的箭头键上移动?

    • 1 个回答
  • Marko Smith

    VirtualBox 无法以 VERR_NEM_VM_CREATE_FAILED 启动

    • 8 个回答
  • Marko Smith

    应用程序不会出现在 MacBook 的摄像头和麦克风隐私设置中

    • 5 个回答
  • Martin Hope
    Saaru Lindestøkke 为什么使用 Python 的 tar 库时 tar.xz 文件比 macOS tar 小 15 倍? 2021-03-14 09:37:48 +0800 CST
  • Martin Hope
    CiaranWelsh 如何减少“vmmem”进程的消耗? 2020-06-10 02:06:58 +0800 CST
  • Martin Hope
    Jim Windows 10 搜索未加载,显示空白窗口 2020-02-06 03:28:26 +0800 CST
  • Martin Hope
    v15 为什么通过电缆(同轴电缆)的千兆位/秒 Internet 连接不能像光纤一样提供对称速度? 2020-01-25 08:53:31 +0800 CST
  • Martin Hope
    andre_ss6 远程桌面间歇性冻结 2019-09-11 12:56:40 +0800 CST
  • Martin Hope
    Riley Carney 为什么在 URL 后面加一个点会删除登录信息? 2019-08-06 10:59:24 +0800 CST
  • Martin Hope
    zdimension 鼠标指针在 Windows 中按下的箭头键上移动? 2019-08-04 06:39:57 +0800 CST
  • Martin Hope
    jonsca 我所有的 Firefox 附加组件突然被禁用了,我该如何重新启用它们? 2019-05-04 17:58:52 +0800 CST
  • Martin Hope
    MCK 是否可以使用文本创建二维码? 2019-04-02 06:32:14 +0800 CST
  • Martin Hope
    SoniEx2 更改 git init 默认分支名称 2019-04-01 06:16:56 +0800 CST

热门标签

windows-10 linux windows microsoft-excel networking ubuntu worksheet-function bash command-line hard-drive

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve