我想遞歸地找到每個目錄中最大的文件

我想遞歸地找到每個目錄中最大的文件

輸出將包括目錄名、檔案名稱和檔案大小。運行命令的每個目錄都有一個(最大檔案)。

如果可能的話,還有該目錄中檔案的平均大小。

目的是可以在目錄中找到比目錄中其他文件大得多的文件,以便可以替換它們

答案1

使用 GNU findsortsed(4.2.2 或更高版本),根據檔案大小排序一次,然後根據目錄路徑再次排序:

find /some/dir -type f -printf '%s %f%h\0' | 
  sort -zrn |
  sort -zut/ -k2 |
  sed -zre 's: ([^/]*)(/.*): \2/\1:'

解釋:

  • 列印檔案大小、名稱和路徑(第一個由空格分隔,後兩個由 分隔/),每個條目均以 ASCII NUL 字元終止。
  • 然後,我們使用大小進行數字排序,假設 NUL 分隔輸出(並且以相反順序,因此最大的檔案在前)。
  • 然後,我們使用第二個分隔欄位中的所有內容(該欄位是包含該檔案的目錄的路徑)sort僅列印第一個唯一條目。/
  • 然後我們使用sed交換目錄和檔案名,這樣我們就得到了一個正常的路徑。

為了獲得可讀取的輸出,請將 ASCII NUL 替換為換行符:

find /some/dir -type f -printf '%s %f%h\0' | 
  sort -zrn |
  sort -zut/ -k2 |
  sed -zre 's: ([^/]*)(/.*): \2/\1:' |
  tr '\0' '\n'

輸出範例:

$ find /var/log -type f -printf '%s %f%h\0' | sort -zrn | sort -zt/ -uk2 | sed -zre 's: ([^/]*)(/.*): \2/\1:' | tr '\0' '\n'
3090885 /var/log/syslog.1
39789 /var/log/apt/term.log
3968 /var/log/cups/access_log.1
31 /var/log/fsck/checkroot
467020 /var/log/installer/initial-status.gz
44636 /var/log/lightdm/seat0-greeter.log
15149 /var/log/lxd/lxd.log
4932 /var/log/snort/snort.log
3232 /var/log/unattended-upgrades/unattended-upgrades-dpkg.log

答案2

結合併findawk可以計算平均值:

find . -type f -printf '%s %h/%f\0'|awk 'BEGIN { RS="\0" } { SIZE=$1; for (i = 1; i <= NF - 1; i++) $i = $(i + 1); NF = NF - 1; DIR=$0; gsub("/[^/]+$", "", DIR); FILE=substr($0, length(DIR) + 2); SUMSIZES[DIR] += SIZE; NBFILES[DIR]++; if (SIZE > MAXSIZE[DIR] || !BIGGESTFILE[DIR]) { MAXSIZE[DIR] = SIZE; BIGGESTFILE[DIR] = FILE } }; END { for (DIR in SUMSIZES) { printf "%s: average %f, biggest file %s %d\n", DIR, SUMSIZES[DIR] / NBFILES[DIR], BIGGESTFILE[DIR], MAXSIZE[DIR] } }'

AWK 腳本以更易讀的方式排列:

BEGIN { RS="\0" }

{
  SIZE=$1
  for (i = 1; i <= NF - 1; i++) $i = $(i + 1)
  NF = NF - 1
  DIR=$0
  gsub("/[^/]+$", "", DIR)
  FILE=substr($0, length(DIR) + 2)
  SUMSIZES[DIR] += SIZE
  NBFILES[DIR]++
  if (SIZE > MAXSIZE[DIR] || !BIGGESTFILE[DIR]) {
    MAXSIZE[DIR] = SIZE
    BIGGESTFILE[DIR] = FILE
  }
}

END {
  for (DIR in SUMSIZES) {
    printf "%s: average %f, biggest file %s %d\n", DIR, SUMSIZES[DIR] / NBFILES[DIR], BIGGESTFILE[DIR], MAXSIZE[DIR]
  }
}

這需要空分隔的輸入記錄(我從穆魯的回答);對於每個輸入記錄,它

  • 儲存大小(供以後使用),
  • 刪除路徑中第一個字元之前的所有內容(因此我們至少正確處理帶有空格的檔案名稱),
  • 擷取目錄,
  • 提取檔案名,
  • 將我們之前儲存的大小加到目錄中的大小總和中,
  • 增加目錄中的檔案數量(這樣我們就可以計算平均值),
  • 如果大小大於儲存的目錄最大大小,或者如果我們尚未在目錄中看到文件,則更新最大文件的資訊。

完成所有操作後,腳本將循環輸入鍵SUMSIZES並輸出目錄、平均大小、最大檔案名稱和大小。

您可以透過管道將輸出sort按目錄名稱排序。如果您想以人性化的形式另外設定尺寸格式,您可以將該printf行變更為

printf "%.2f %d %s: %s\n", SUMSIZES[DIR] / NBFILES[DIR], MAXSIZE[DIR], DIR, BIGGESTFILE[DIR]

然後將輸出通過管道傳輸到numfmt --field=1,2 --to=iec.您仍然可以按目錄名稱對結果進行排序,只需從第三個欄位開始排序:sort -k3

答案3

茲什通配符模式對於你正在做的事情非常有用。具體來說,zsh可以透過類型、大小等屬性來匹配文件全域限定符。 Glob 限定符也允許對匹配項進行排序。

例如,在 zsh 中,*(.DOLN[1])擴展為目前目錄中最大檔案的名稱。*是文件名的模式(匹配所有內容,除了可能的點文件,取決於 shell 選項)。限定符.將匹配限制為常規文件,D導致*包含點文件,OL按遞減大小(“長度”)排序,N如果根本沒有匹配文件,則導致擴展為空,並[1]僅選擇第一個匹配。

您可以使用 遞歸枚舉目錄**/。例如,以下循環遞歸地迭代目前目錄及其子目錄的所有子目錄:

for d in **/*(/); do … done

您可以使用zstat存取文件的大小和其他元數據,而無需依賴其他工具進行解析。

zmodload -F zsh/stat b:zstat
files=(*(DNoL))
zstat -A sizes +size -- $files
total=0; for s in $sizes; do total+=$s; done
if ((#sizes > 0)); then
  max=$sizes[-1]
  average=$((total/#sizes))
  median=$sizes[$((#sizes/2))]
fi

答案4

考慮使用 baobab 或一些類似的軟體,其中一個或多個可能包含在您的發行版中。他們很好地視覺化了問題目錄。

  • 猴麵包樹
  • JDisk報告
  • NCDU
  • K4DirStat
  • QDirStat
  • 廣東省地圖

http://alternativeto.net/software/baobab/?platform=linux

猴麵包樹的手冊頁告訴了它它是怎麼回事。

$> man baobab
BAOBAB(1)

NAME
       Baobab - A graphical tool to analyse disk usage

SYNOPSIS
       baobab  [directory]

DESCRIPTION
       baobab is able to scan either specific folders or the whole filesys-
       tem (local and remote), in order to give the user a graphical tree
       representation including each directory size or percentage in the
       branch.  It also auto-detects in real-time any change made to your
       home directory as far as any mounted/unmounted device. A graphical
       treemap window is also provided for any selected folder.

       A detailed documentation on the program could be read at:
       http://www.gnome.org/projects/baobab

AUTHOR
       Fabio MARZOCCA <[email protected]>



                                                                     BAOBAB(1)

相關內容