【问题标题】:Finding the maximum number of files in a subdirectory查找子目录中的最大文件数
【发布时间】:2017-10-24 02:30:15
【问题描述】:

所以我正在尝试编写一个 bash 脚本,该脚本将查看指定文件夹中的所有子目录,并返回单个子目录中的最大文件数。这是我现在拥有的:

#!/bin/bash   
maxCount=0 
fileCount=0 
# script that writes out all the directories and how many files are in each directory

find ./testdata/ -maxdepth 1 -mindepth 1 -type d | while read dir; do  #loop all subdirectories    
fileCount= find "$dir" -type f | wc -l #count all the files in subdirectory

    if [ $fileCount -gt $maxCount ] #if the count is higher than the max     
    then
        maxCount= "$fileCount" #set the count equal to the max
    fi

    done

#print out how many messages are in the thread    
echo "$maxCount"

首先,变量 fileCount 设置不正确。 find "$dir" -type f | 的输出wc -l 仍然被设置为标准输出,因此脚本一直返回零。

当前输出示例:

1
1
2
1
1
1
0

最后一个零是 echo "$maxCount" 的输​​出

不太确定我做错了什么。谢谢!

使用 xfce4 终端

【问题讨论】:

  • 由于while循环在一个新的子shell中执行,一旦循环终止,内部使用的变量将不可用
  • @etopylight 那么我怎样才能保留变量值呢?
  • 一个简单的解决方法是使用命令分组,它使用花括号使这些命令和变量在同一范围内共存,例如{while read dir; ... echo "$maxCount"} 应该可以工作跨度>
  • 抱歉打错了代码,正确的例子应该是{ while read dir; ... echo "$maxCount"; },注意{while之间需要额外的空格以及最后一个命令和}之间的分号
  • 很高兴为您提供帮助:)

标签: bash unix subdirectory


【解决方案1】:

您可以使用以下命令执行您想要的操作,该命令利用find-exec 选项

find ./testdata/  -maxdepth 1 -mindepth 1 -type d -exec bash -c 'find {} -type f | wc -l' \; | sort -n | tail -n 1

和你的方法一样,这条线

fileCount= find "$dir" -type f | wc -l #count all the files in subdirectory

=find 之间不应有空格,您应该有一个 Command Substitution 将值分配给变量 fileCount,如下所示:

fileCount=$(find "$dir" -type f | wc -l)

如果你想坚持 for 循环:

find . -maxdepth 1 -mindepth 1 -type d | while read dir;do
    cnt=$(find ${dir} -type f | wc -l)
    echo ${cnt}   
done | sort -n | tail -n 1

【讨论】:

  • 命令替换修复了输出问题,但 maxCount 仍然没有从 0 改变
  • @etopylight 评论解释了变量不持有价值的原因
【解决方案2】:

正确的格式:

#!/bin/bash   
maxCount=0 
fileCount=0 
# script that writes out all the directories and how many files are in each directory

find ./testdata/ -maxdepth 1 -mindepth 1 -type d | { while read dir; do  #loop all subdirectories    
fileCount=$(find "$dir" -type f | wc -l) #count all the files in subdirectory

    if [ $fileCount -gt $maxCount ] #if the count is higher than the max     
    then
        maxCount= "$fileCount" #set the count equal to the max
    fi

    done

#print out how many messages are in the thread    
echo "$maxCount"; }

变化:

fileCount=${find "$dir" -type f | wc -l}

使用Command Substitution 将fileCount 变量正确设置为正确值

{ while read dir; do ... echo "$maxCount"; }

在回显结果时,使用Command Grouping 将 maxCount 保持在与 while 循环相同的范围内。

希望这对将来的其他人有所帮助!

【讨论】:

  • fileCount=${find "$dir" -type f | wc -l}?你确定它对你有用吗?
  • @codeforester 输入错误,应该用括号代替。
  • 对不起,明白为什么我的回答是错误的。我已经删除了我的反对票。并删除了我的答案。我早些时候对你提出的问题表示赞同。和平!
【解决方案3】:

你可以在纯 Bash 中更有效地做到这一点:

#!/bin/bash

# build a hash of directories and file counts
declare -A file_hash
while read -r -d '' file; do     # read the null delimited output of find
  dir="${file%%/*}"              # extract **top dirname** from file path
  ((file_hash[$dir]++))          # increment the count for this dir
done < <(find . -type f -print0) # find all files and output them with a null delimiter
                                 # this will gracefully handle files or directories that have new lines in their name

# find the top directory name with the biggest file count
max=0
for i in "${!file_hash[@]}"; do
  count="${file_hash[$i]}"
  ((count > max)) && { max=$count; max_dir=$i; }
done
printf 'max_dir=[%s], max_count=[%s]\n' "$max_dir" "$max"

在这种方法中,我们使用find 对顶级子目录进行一次扫描。当有大量目录时,这会很好。

【讨论】:

  • 这不是我的问题。如果我希望有人为我做我的工作,我会直接问这个。感谢您对我的东西投反对票,因为我不接受您的回答。
  • 最后,通过调用find,在纯 Bash 中找到了正确的方法。诀窍是通过find 获取所有文件(跨所有子目录),然后从每个路径中提取顶级目录名称并将其用作哈希键。
猜你喜欢
  • 1970-01-01
  • 2012-09-13
  • 1970-01-01
  • 2017-05-07
  • 2017-08-21
  • 1970-01-01
  • 1970-01-01
  • 2021-11-21
  • 2012-02-13
相关资源
最近更新 更多