我想递归搜索目录树并列出每个文件夹中名称与给定字符串对应的可用文件数量。实际上,我想返回以下结果:
ls -l | wc -l
对于我通过 识别的每个文件夹find
。
代码
下面的代码正确列出了 name 包含的每个文件夹中的文件数量神奇数据细绳。
find /path/to/cool/stuff \
-maxdepth 4 \
-type d \
-name '*Magic Data*' \
-print0 | xargs \
--verbose \
-0 -I {} ls -l {}
我想扩展它并将结果传送ls
到wc -l
。
试图
find /path/to/cool/stuff \
-maxdepth 4 \
-type d \
-name '*Magic Data*' \
-print0 | xargs \
--verbose \
-0 -I {} ls -l {} | wc -l
这失败并打印:
ls -l /path/to/cool/stuff/some/folders/Magic Data
ls -l /path/to/cool/stuff/some/folders2/Magic Data
所需输出
/path/to/cool/stuff/some/folders/Magic Data 29
/path/to/cool/stuff/some/folders2/Magic Data 30
所需的输出将包含:
- 搜索文件夹的完整路径
- 的输出
wc -l
,在本例中反映非隐藏文件的计数
答案1
解决这个问题有两种主要方法:
修改
find
命令,使其仅进入您感兴趣的目录,然后x
为其中找到的每个文件打印一个字符(例如 )。然后计算用 产生的该字符的数量wc -l
。输出字符比路径名更安全,因为 Unix 中的路径名可能包含换行符。这个解决方案有点棘手,因为它涉及使用-prune
忽略我们不感兴趣的目录,或者! -path
.就像您到目前为止所做的那样找到目录,然后使用内联脚本来计算其中的文件数量。这更简单,我将在下面展示。
find /path/to/cool/stuff -maxdepth 4 -type d -name "*Magic Data*' \
-exec bash -O dotglob -c '
dir=$1
set -- "$dir"/*
printf "%s %d\n" "$dir" "$#"' bash {} ';'
在这里,我们像您一样找到目录,然后,对于每个目录,我们运行这个简短的bash
脚本:
dir=$1
set -- "$dir"/*
printf "%s %d\n" "$dir" "$#"
这从命令行获取目录的路径名(由 给出find
),并扩展*
其中的 glob 模式。通过在脚本的命令行上设置dotglob
shell 选项,我们保证也计算隐藏文件和目录(删除-O dotglob
以不计算隐藏名称)。
我们将所有名称作为参数进行扩展set
,这会将位置参数设置为扩展的条目。位置参数的数量可用作$#
,因此它也是该特定目录中的文件数。
有关的:
答案2
从您尝试的解决方案开始,这是完成此任务的方法:
find /path/to/cool/stuff \
-maxdepth 4 \
-type d \
-name '*Magic Data*' \
-exec sh -c '
for d do
printf "%s: " "$PWD/$d"
find "$d/." -maxdepth 1 ! -name . -printf "\\n" | wc -l
done
' find_sh {} +
解释:
- 直到
find
-英目标目录,遵循您的食谱。 - 一旦我们找到目标目录,即那些在其基名中某处具有字符串“Magic Data”的目录,我们将它们收集在一堆中,并通过其参数列表
{} +
将它们交给shell :sh
sh -c '...' find_sh {} +
- 其初始参数
sh
是第零个参数$0
,因此可以给它任何名称,在本例中我们将其命名为find_sh
。这是将显示在进程列表中的名称。 - 目标目录束进入
{} +
并形成$1 $2 $3 ...
我们正在生成的 shell 的参数。 - 在我们刚刚启动的 shell 中,我们为在目标目录中找到的每个文件发出一个换行符(除了它本身),即
! -name .
OTW,目标目录名称也会计入 wc -l 输出中。
答案3
您也可以使用以下命令来实现您想要的
在这里,我用来exec
执行sh
shell,然后使用-c
option 执行给它的命令。在你的情况下,命令是ls -1 | wc -l
find /path/to/cool/stuff -maxdepth 4 -type d -name '*Magic Data*' -print0 -exec sh -c "ls -1 {} | wc -l" \;