在 for 循环内部运行时如何获取通过管道传输到 wc 的 ls 结果?

在 for 循环内部运行时如何获取通过管道传输到 wc 的 ls 结果?

因此,我尝试将其设为单个命令,而不必将数据转储到文件中,然后对文件进行 cat 并将输出通过管道传输到 wc -l。整行代码如下所示:

for file in `grep Rawdata freeze2-1.out | awk '{print $6}'`
 do
  ls -1 /appdata/frozen_files/$file | wc -l
 done

但输出给了我每行的计数,而不是整个输出的总数。无论如何,我可以在获得所有文件的单个数字的输出的情况下完成此操作,还是必须重定向到文件并执行另一个步骤?

答案1

您正在尝试计算 freeze2-1.out 文件中字段 6 命名的目录中的文件总数,但仅限于该文件该行某处出现“Rawdata”的位置。

您最初的帖子中的主要错误只是逻辑或位置上的一个错误;你要求wc -l计算各个行的数量里面询问整个循环提供的总行数的循环。这就是大多数现有答案正在纠正的问题。

我制作了一个示例 freeze2-1.out 文件,以便我可以“在家玩”;这是我放入的内容:

Rawdata 2 3 4 5 file1
Rawdata 2 3 4 5 file2
Rawdata 2 3 4 5 file3

我还填充了一个相对的名为“appdata/frozen_files”的目录,目录名称基于上面的字段 6。请注意,您的实际路径是绝对以 /appdata/frozen_files 开头的路径。我在 file1 中放置了 1 个文件,在 file2 中放置了 2 个文件,在 file3 中放置了 3 个文件,总共 6 个文件。

我建议的第一个改进是将grep和结合起来awk,因为 awk 可以进行模式匹配。罗曼·佩雷赫雷斯特他们的回答中也这样做了:

awk '/Rawdata/ { print $6 }' freeze2-1.out

示例输出为:

file1
file2
file3

我将在这里指出,由于 awk 根据空格、制表符和换行符分割字段,因此专门打印字段 6 意味着每行输出将有一个不带空格的单词。

有几种方法可以计算目录中的文件数量。使用的ls -1 | wc -lA方式,但在文件名嵌入换行符的特殊情况下会失败;您可以使用 手动创建这样的文件touch $'file\nname'。由于 awk 正在读取由换行符分隔的输入行,因此我们不会在这里遇到这种特殊情况,但我想提一下。例如:

# create the file
$ touch $'file\nname'

# check the listing; looks okay so far
$ ls -1
appdata
file?name
freeze2-1.out

# count them up
$ ls -1 | wc -l
4 

# woops! should be 3!

因此,我将演示另外两种方法来计算目录中的文件数量。

第一个方法使用set内置函数获取其参数并将它们转换为以 $1、$2、$3 等命名的位置参数。

$ sum=0
$ for file in $(awk '/Rawdata/ { print $6 }' freeze2-1.out)
  do
    set -- "appdata/frozen_files/${file}/"*
    sum=$((sum + $#))
  done
$ echo "$sum"
6

这会将计数器初始化sum为零,然后循环遍历 awk 输出中的文件名。它set使用带引号的目录路径进行调用,后跟*shell glob,它扩展到该目录中的所有(非隐藏)文件。这ls -1与排除隐藏文件(以句点开头的文件)的行为相匹配。参数的数量由特殊变量 给出$#,我们将其添加到循环中sum,然后在最后打印它。

对于支持数组的 shell,第二种方法是将通配符文件名放入数组中,然后对数组的元素进行计数:

$ sum=0
$ for file in $(awk '/Rawdata/ { print $6 }' freeze2-1.out )
  do
    n=("appdata/frozen_files/${file}"/*)
    sum=$((sum + ${#n[@]}))
  done
$ echo "$sum"
6

答案2

将字数移至末尾;

for file in $(grep Rawdata freeze2-1.out | awk '{print $6}')
 do
  ls -1 /appdata/frozen_files/$file
 done | wc -l

或求和;

C=0
for file in $(grep Rawdata freeze2-1.out | awk '{print $6}')
 do
  C=$[$C+$(ls -1 /appdata/frozen_files/$file | wc -l)]
 done
echo $C;

或者也许使用 find 如果您的文件结构可以匹配模式(或正则表达式)

find /appdata/frozen_files/ -iname '*.raw' |wc -l

相关内容