【问题标题】:Bash script to find largest file by parsing text tree通过解析文本树来查找最大文件的 Bash 脚本
【发布时间】:2017-03-18 14:21:19
【问题描述】:

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

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

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

.
[        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 条目,但没有得到任何运气。

Read a file line by line assigning the value to a variable

Looping through the content of a file in Bash?

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

请注意,tree 能够将输出格式化为 xml 文件,使用标签和属性,如 <directory name="fileName" size="XXXX"></directory> 所以如果解析xml文件更容易,那也很好。

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

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

【问题讨论】:

  • 详细说明您的问题:按文件大小或文件中的行数查找最大文件
  • 对不起,我的意思是大小,括号之间的数字以字节为单位。无论如何,解决方案真的很简单。谢谢

标签: linux bash parsing text


【解决方案1】:

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

sort -V yourList.txt | head -n 

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

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

如果您只想要文件,请将| sed 's/^[0-9]\+\t//' 添加到末尾。

【讨论】:

    【解决方案2】:

    不要使用tree。相反,只需遍历文件并调用stat 以获取每个文件的大小,记住目前看到的最大文件。在bash4 或更高版本,就这么简单

    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
    

    【讨论】:

      猜你喜欢
      • 2011-10-11
      • 2020-02-09
      • 1970-01-01
      • 1970-01-01
      • 2020-06-16
      • 2013-08-30
      • 1970-01-01
      • 2012-10-05
      • 2012-07-22
      相关资源
      最近更新 更多