Ls
ls 命令不適用於包含大量文件的目錄
我有一個包含大約500 萬個文件的目錄。當我試圖
ls
從這個目錄中執行命令時,我的系統消耗了大量的記憶體,並在一段時間後掛起。除了使用命令之外,有沒有一種有效的方法來列出文件ls
?
ls
實際上對文件進行排序並嘗試列出它們,如果我們試圖在目錄中列出超過一百萬個文件,這將成為一個巨大的成本。如此連結中所述,我們可以使用strace
或find
列出文件。但是,這些選項對我的問題似乎也不可行,因為我有 500 萬個文件。經過一番Google搜尋後,我發現如果我們使用 列出目錄getdents()
,它應該會更快,因為ls
和find
庫Python
使用readdir()
的速度較慢,但getdents()
在下面使用。
getdents()
我們可以從這裡找到列出文件的 C 程式碼:/* * List directories using getdents() because ls, find and Python libraries * use readdir() which is slower (but uses getdents() underneath. * * Compile with * ]$ gcc getdents.c -o getdents */ #define _GNU_SOURCE #include <dirent.h> /* Defines DT_* constants */ #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/syscall.h> #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0) struct linux_dirent { long d_ino; off_t d_off; unsigned short d_reclen; char d_name[]; }; #define BUF_SIZE 1024*1024*5 int main(int argc, char *argv[]) { int fd, nread; char buf[BUF_SIZE]; struct linux_dirent *d; int bpos; char d_type; fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY); if (fd == -1) handle_error("open"); for ( ; ; ) { nread = syscall(SYS_getdents, fd, buf, BUF_SIZE); if (nread == -1) handle_error("getdents"); if (nread == 0) break; for (bpos = 0; bpos < nread;) { d = (struct linux_dirent *) (buf + bpos); d_type = *(buf + bpos + d->d_reclen - 1); if( d->d_ino != 0 && d_type == DT_REG ) { printf("%s\n", (char *)d->d_name ); } bpos += d->d_reclen; } } exit(EXIT_SUCCESS); }
將上面的 C 程序複製到需要列出文件的目錄中。然後執行以下命令。
gcc getdents.c -o getdents ./getdents
計時範例:
getdents
可能比 快得多ls -f
,具體取決於系統配置。以下是一些時序,展示了在計算集群中通過 NFS 掛載列出包含約 500k 文件的目錄時速度提高了 40 倍。每個命令立即連續執行 10 次,首先getdents
是 ,然後是ls -f
。第一次執行明顯慢於其他所有,可能是由於 NFS 記憶體頁面錯誤。(除此之外:在這個掛載上,該d_type
欄位是不可靠的,因為許多文件顯示為“未知”類型。)command: getdents $bigdir usr:0.08 sys:0.96 wall:280.79 CPU:0% usr:0.06 sys:0.18 wall:0.25 CPU:97% usr:0.05 sys:0.16 wall:0.21 CPU:99% usr:0.04 sys:0.18 wall:0.23 CPU:98% usr:0.05 sys:0.20 wall:0.26 CPU:99% usr:0.04 sys:0.18 wall:0.22 CPU:99% usr:0.04 sys:0.17 wall:0.22 CPU:99% usr:0.04 sys:0.20 wall:0.25 CPU:99% usr:0.06 sys:0.18 wall:0.25 CPU:98% usr:0.06 sys:0.18 wall:0.25 CPU:98% command: /bin/ls -f $bigdir usr:0.53 sys:8.39 wall:8.97 CPU:99% usr:0.53 sys:7.65 wall:8.20 CPU:99% usr:0.44 sys:7.91 wall:8.36 CPU:99% usr:0.50 sys:8.00 wall:8.51 CPU:100% usr:0.41 sys:7.73 wall:8.15 CPU:99% usr:0.47 sys:8.84 wall:9.32 CPU:99% usr:0.57 sys:9.78 wall:10.36 CPU:99% usr:0.53 sys:10.75 wall:11.29 CPU:99% usr:0.46 sys:8.76 wall:9.25 CPU:99% usr:0.50 sys:8.58 wall:9.13 CPU:99%
避免使用排序:
ls --sort=none # "do not sort; list entries in directory order"
或者,等效地:
ls -U