首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过解析文本树找到最大文件的Bash脚本

通过解析文本树找到最大文件的Bash脚本
EN

Stack Overflow用户
提问于 2017-03-18 14:21:19
回答 2查看 239关注 0票数 0

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

我发现,如果我使用"tree“来生成所有文件的文本表示,那么我就可以使用脚本来比较大小并输出最大的文件。

最后,我得到了一个类似于以下内容的文本文件

代码语言:javascript
复制
.
[        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查看了其他一些堆栈溢出条目,但没有得到任何结果。

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

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

文件夹也列出在那里,但我们可以忽略这一点。

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-03-18 14:30:25

只需按数字对列表进行排序,并获取第一行:

代码语言:javascript
复制
sort -V yourList.txt | head -n 

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

代码语言:javascript
复制
find . -type f -exec du -b {} + | sort -nr | head -n 1

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

票数 1
EN

Stack Overflow用户

发布于 2017-03-18 14:56:58

不要使用tree。相反,只需遍历文件并调用stat来获取每个文件的大小,记住到目前为止最大的文件。在bash 4或更高版本中,它非常简单

代码语言:javascript
复制
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,您需要定义一个递归函数来模拟**

代码语言:javascript
复制
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])

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

代码语言:javascript
复制
find . -exec stat -c '%s %n' {} + | sort -k2,2nr | head -1

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

代码语言:javascript
复制
finfo -v size -s "$f"  # equivalent to size=$(stat -c %s "$f"), but all in shell
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42875527

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档