繁体   English   中英

Bash脚本通过解析文本树来查找最大的文件

[英]Bash script to find largest file by parsing text tree

我需要编写一个脚本来查找给定目录(包括其子目录)中的最大文件。

我发现如果使用“树”来生成所有文件的文本表示,也许我可以使用脚本来比较大小并输出最大的文件。

我最终得到一个看起来像这样的文本文件

.
[        939]  "./Documents/Alfa/driver/wlan0up"
[        234]  "./Documents/Alfa/driver/wpa1.conf"
[    1623520]  "./Documents/Alfa/driver/wpa_supplicant-0.5.5.zip"
[    5488640]  "./Documents/Alfa/R36-V1.2.1.2b6.img"
[       3385]  "./Documents/C code/Ide.s"
[       4096]  "./Documents/fluxion-master"
[         25]  "./Documents/fluxion-master/_config.yml"
[       4096]  "./Documents/fluxion-master/docs"
[      35141]  "./Documents/fluxion-master/docs/LICENSE"
[      83788]  "./Documents/fluxion-master/fluxion"
~~ long list of other files
[       6909]  "./.ZAP/session/untitled2.script"
[      64411]  "./.ZAP/zap.log"
[       4096]  "./.zenmap"
[          0]  "./.zenmap/recent_scans.txt"
[       2018]  "./.zenmap/scan_profile.usp"
[         85]  "./.zenmap/target_list.txt"
[       1486]  "./.zenmap/zenmap.conf"
[     409600]  "./.zenmap/zenmap.db"
[          5]  "./.zenmap/zenmap_version"

429 directories, 3327 files

现在,我需要做的是让脚本通读列表并比较大小,直到列表结束,然后输出最大文件的名称和大小。

我使用sed和grep进行了一些其他stackoverflow条目,但是没有任何运气。

逐行读取文件,将值分配给变量

在Bash中循环浏览文件的内容?

https://codereview.stackexchange.com/questions/59417/extracting-data-from-text-file-in-bash-using-awk-grep-head-and-tail

请注意,tree能够使用诸如<directory name="fileName" size="XXXX"></directory>这样的标签和属性将输出格式化为xml文件,因此,如果解析xml文件比较容易,那也可以。

文件夹也列在其中,但我们可以忽略它。

任何帮助,将不胜感激,谢谢

只需按数字对列表进行排序并抓住第一行:

sort -V yourList.txt | head -n 

我觉得您有一个相当大的脚本来生成列表。 该列表也不安全。 如果文件名包含换行符(是的,在Linux上是可能的),会发生什么? 以下命令在当前目录(包括子目录)中找到最大的文件,并打印其大小和名称。

find . -type f -exec du -b {} + | sort -nr | head -n 1

如果只需要文件,请添加| sed 's/^[0-9]\\+\\t//' | sed 's/^[0-9]\\+\\t//'结束。

不要用tree 相反,只需遍历文件并调用stat即可获取每个文件的大小,并记住迄今为止看到的最大文件。 bash 4或更高版本中,它很简单

shopt -s globstar
for f in **/*; do
    size=$(stat -c %s)
    if (( size > max_size )); then
        max_size=$size
        max_file=$f
    fi
done

如果您有可用的zsh ,则就像fname=$(zsh -c 'print **/*(OL[1])')

使用早期版本的bash ,您需要定义一个递归函数来模拟**

dir_iter () {
    for f in "$1"/*; do
        if [[ -d $f ]]; then
            dir_iter "$f"
        else
            size=$(stat -c %s)
            if ((size > max_size)); then
                max_size=$size
                max_file=$f
            fi
        fi
    done
}
dir_iter .

(请注意,您应查询本地文档以获取stat命令的确切形式,该形式可能有所不同。例如,BSD stat使用-f而不是-c 。)


一个反对意见是它需要多次调用stat 这很昂贵,但是避免了处理文件名序列的问题(这种情况很少见)(当文件名可以包含换行符时,这很复杂)。

如果您有zsh可用,则就像max_file=$(zsh -c 'print **/*(OL[1])') 如果您实际使用的是 zsh ,则仅print -v max_file **/*(OL[1])

如果您决定不担心使用换行符的文件名,则可以执行以下操作:

find . -exec stat -c '%s %n' {} + | sort -k2,2nr | head -1

我将处理包含换行符的文件名作为读者的练习。 通常,我只会使用一种可以正确表示任意字符串序列的语言。 另一个选择是查看bash源分发的examples/loadables目录中的finfo命令。 这是创建一个shell内置命令的示例,该命令执行与stat相同的操作而不创建新进程。 可以对其进行修改,以添加与printf支持的选项类似的-v选项,以便您可以从输出中设置shell变量。

finfo -v size -s "$f"  # equivalent to size=$(stat -c %s "$f"), but all in shell

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM