2017-03-18 46 views
0

我需要編寫一個腳本來查找給定目錄(包括其子目錄)中最大的文件。Bash腳本通過解析文本樹來查找最大文件

我想如果我用「樹」來生成所有文件的文本表示,也許我可以讓腳本比較大小並輸出最大的文件。

我結束了,看起來像這樣

. 
[  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 

現在一個文本文件,我需要的是,直到列表結束,然後輸出最大的已經在列表中讀了劇本,並比較大小文件的名稱和大小。

我經歷了一些其他的stackoverflow條目,使用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

請注意,樹是可以格式化輸出爲XML文件,使用標籤和屬性,如<directory name="fileName" size="XXXX"></directory> 所以如果解析XML文件更容易,這也可以。

文件夾也列在那裏,但我們可以忽略它。

任何幫助,將不勝感激, 感謝

+0

詳細說明您的問題:找到*最大的文件*按文件大小或按文件中的行數? – RomanPerekhrest

+0

對不起,我的意思是大小,括號內的數字是以字節爲單位..無論如何解決方案非常簡單..謝謝 – Mo3tasm

回答

1

只是排序列表由數字和搶第一行:

sort -V yourList.txt | head -n 

我有,你有一個相當大的腳本產生的感覺名單。該名單也有點不安全。如果一個文件名包含一個換行符(是的,這在Linux上是可行的)會發生什麼?以下命令查找最大的文件並在當前目錄(包括子目錄)中打印其大小和名稱。

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

如果您只想要該文件,請將| sed 's/^[0-9]\+\t//'添加到最後。

1

請勿使用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相同的操作。可以修改它以添加一個-v選項,類似於printf支持的選項,以便您可以從輸出中設置shell變量。

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