作为我的 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 命令呢?
一个简单的扫描
find
将是:glob 模式中的尾部斜杠将结果限制为仅目录。
分析
请注意,您
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 为您计算目录:
set --
将所有名称存储为位置参数,然后echo "$#"
打印数字。set
是内置的,它不应该受到argument list too long
. 我特意使用了一个子shell,所以当前shell的位置参数不受影响。我可以使用一个单独的数组(就像其他答案一样),但是有一个潜在的问题。Bash 允许您设置大量的位置参数。一方面它很好,因为您想要计算大量目录。另一方面,参数需要作为字符串存储在内存中,即使您只想要它们的计数。请注意,如果您这样做:
那么
$()
无论如何,内部都会在子shell中执行,因此您不需要额外的括号。您可以选择在子shell 中使用数组。在任何情况下,子shell都会立即退出echo
,内存会尽快释放。但如果你这样做:如果您不这样做,
unset dirs
那么阵列将成为负担。立即死亡并释放内存的子shell 比您可能忘记取消设置的消耗内存的数组要好。一种或另一种方式,所有扩展的单词都需要存储(如果只是暂时在子shell中),然后才能获得它们的计数。出于这个原因,您可能更喜欢
find
允许wc
即时计数。或
find
+wc
一个基本的解决方案是在另一个答案中,重点是
-type d
. 这个想法(正确引用):可能会失败,因为:
-maxdepth
并且-mindepth
不便携;wc -l
。如果您
find
支持-printf
(因此它很可能支持-maxdepth
and-mindepth
),那么您可以通过打印单个字节并计算它们来解决后一个问题:其中
a
是一个任意的单字节字符。一个便携式(但速度稍慢)的解决方案是这样的:
子shell
cd
不影响当前shell 的当前工作目录。我首先使用它是因为cd -- "$storage"/
它允许我稍后引用它,因此无需修剪即可轻松排除它。如果没有,我将需要使用类似的东西,但随后会解释为一种模式;所以这通常会失败。$storage
.
cd
! -path "$storage"
find
$storage
另一方面,如果您被允许
r
读取目录但不能x
执行(cd
进入,请参阅此答案),那么cd
将不起作用,而没有cd
可能的解决方案。笔记
在双破折号和尾部斜杠中,使路径类似于
cd -- "$storage"/
甚至被解释为实际路径名。-foo
-
find-sh
在这里解释:什么是第二个 shsh -c 'some shell code' sh
?.如果您不想计算隐藏目录,请
! -name '.*'
在-prune
.-type d
与目录的符号链接不匹配。为了比较:shell globbing patterns like*/
do 匹配它们。如果要下降到子目录并计算整个子树,请省略
-prune
.shopt
不便携。sh
我不知道在纯shopt -s nullglob
Bash中做的事情没有直接的方法。你的问题被标记为bash,所以这应该不是问题。