![스파스 파일의 내용을 보는 방법은 무엇입니까?](https://rvso.com/image/154474/%EC%8A%A4%ED%8C%8C%EC%8A%A4%20%ED%8C%8C%EC%9D%BC%EC%9D%98%20%EB%82%B4%EC%9A%A9%EC%9D%84%20%EB%B3%B4%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
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
인터넷 검색을 한 후 파일이 희소 파일일 수 있다는 결론에 도달했습니다. 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 터미널에서 파일의 구멍/0 없이 파일 내용만 볼 수 있는 방법이 있는지 알고 싶습니다.
답변1
최신 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
참고: 작업을 단순하게 유지하기 위해 모든 파일 열기 코드(항상 으로 사용되어야 함)와 플래그로 열린 tty sparse_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");
}
}
}