Linux
如何查看稀疏文件的內容?
當我使用 ls -l 檢查大小時,“文件”的大小顯示為 15TB
ls -l total 16 -rw-r--r-- 1 root root 15393162788865 May 30 13:41 file
當我使用 du 命令檢查“文件”的大小時,它顯示以下內容。
du -a file 12 file
經過一番Google搜尋,我得出一個結論,該文件可能是一個稀疏文件。當我閱讀它時,像 less、tail、cat、hexdump 等命令需要很長時間。
這是filefrag的輸出。
filefrag -e file Filesystem type is: ef53 File size of file is 15393162788865 (3758096385 blocks of 4096 bytes) ext: logical_offset: physical_offset: length: expected: flags: 0: 0.. 0: 22261760.. 22261760: 1: 1: 3169274812..3169274812: 22268860.. 22268860: 1: 3191536572: 2: 3758096383..3758096383: 22271999.. 22271999: 1: 611090431: last file: 3 extents found
我想知道是否有一種方法可以從 Linux 終端僅查看文件的內容而沒有其中的孔/零。
在較新的 linux 系統上,其中的
SEEK_DATA
和SEEK_HOLE
擴展lseek(2)
允許應用程序在讀取稀疏文件時跳過“漏洞”。在較舊的系統上,
ioctl(FIBMAP)
可以使用並且可以直接從底層設備讀取數據(儘管FIBMAP
需要CAP_SYS_RAWIO
功能)。不幸的是,我不知道任何使用任何 coreutils / 標準實用程序。
這是一個小型
sparse_cat
展示,它使用這些展示以便立即從非常大的稀疏文件中轉儲數據。例子:
$ cc -Wall -O2 sparse_cat.c -s -o sparse_cat $ echo 1st | dd conv=notrunc status=none bs=1 seek=10M of=/tmp/sparse $ echo 2nd | dd conv=notrunc status=none bs=1 seek=10G of=/tmp/sparse $ echo 3rd | dd conv=notrunc status=none bs=1 seek=10T of=/tmp/sparse $ ls -l /tmp/sparse -rw-r--r-- 1 ahq ahq 10995116277764 May 30 16:29 /tmp/sparse $ ./sparse_cat </tmp/sparse >/dev/tty a00000 a01000 1st 280000000 280001000 2nd a0000000000 a0000000004 3rd
注意:為了簡單起見,我省略了任何文件打開程式碼(它應該始終用作
sparse_cat < input
,而不是)以及使用標誌打開的 ttyssparse_cat input
之間的不良互動的任何變通方法(顯式使用)。sendfile(2)``O_APPEND``>/dev/tty
另請注意,數據/孔範圍具有塊粒度——
1st
上面範例中的字元串實際上後面跟著block size - 4
nul 字節。sparse_cat.c
#define _GNU_SOURCE #include <err.h> #include <errno.h> #include <fcntl.h> #include <limits.h> #include <stdio.h> #include <unistd.h> #include <sys/sendfile.h> int main(void){ off_t hole, data, pos, len; typedef unsigned long long ull; for(hole = 0;; data = hole){ if((data = lseek(0, hole, SEEK_DATA)) == -1){ if(errno == ENXIO) return 0; err(1, "lseek +data"); } if((hole = lseek(0, data, SEEK_HOLE)) == -1) err(1, "lseek +hole"); dprintf(2, "%16llx %16llx\n", (ull)data, (ull)hole); for(pos = data; pos < hole;){ len = hole - pos; if(len > INT_MAX) len = INT_MAX; if((len = sendfile(1, 0, &pos, len)) == 0) return 0; if(len < 0) err(1, "sendfile"); } } }