내 시스템이나 특정 디렉터리 트리에서 모든 스파스 파일을 쉽게 찾을 수 있는 방법이 있습니까?
관련이 있다면 zsh
Ubuntu 12.04를 사용하고 있지만 bash/sh에 대한 보다 일반적인 Unix-y 답변은 괜찮을 것입니다.
편집하다: 명확히 말하면 개별 파일의 희소성 상태를 확인하는 것이 아니라 희소성 파일을 찾고 있습니다.
답변1
이 플래그를 지원하는 SEEK_HOLE
lseek
시스템(및 파일 시스템)(예: ext4의 Ubuntu 12.04)에서 해당 값이 SEEK_HOLE
Linux와 같이 4라고 가정합니다.
if perl -le 'seek STDIN,0,4;$p=tell STDIN;
seek STDIN,0,2; exit 1 if $p == tell STDIN'< the-file; then
echo the-file is sparse
else
echo the-file is not sparse
fi
쉘 구문은 POSIX입니다. 내부에 휴대할 수 없는 물건은 perl
이렇게 생겼습니다 SEEK_HOLE
.
lseek(SEEK_HOLE)
첫 시작을 찾고 있어요구멍파일에 있거나 취약점이 발견되지 않은 경우 파일의 끝 부분에 있습니다. 위에서 우리는 lseek(SEEK_HOLE)
파일의 끝( 과 같은 위치)으로 이동할 때 파일이 희박하지 않다는 것을 알고 있습니다 lseek(SEEK_END)
.
스파스 파일을 나열하려면 다음을 수행하십시오.
find . -type f ! -size 0 -exec perl -le 'for(@ARGV){open(A,"<",$_)or
next;seek A,0,4;$p=tell A;seek A,0,2;print if$p!=tell A;close A}' {} +
GNU find
(버전 4.3.3부터)는 -printf %S
보고 해야 합니다.희소성파일의. 그것은 사용한다프로스트슈츠의 답변디스크 사용량과 파일 크기의 비율을 고려하기 때문에 모든 희소 파일 속성을 보고한다고 보장할 수 없습니다(예: 파일 시스템 수준에서 압축이 수행되는 경우 또는 홀 절약이 파일 시스템 인프라 오버헤드를 보상하지 못하는 경우 또는 대용량 확장 파일의 경우) ), 구현되지 않은 시스템이나 구현되지 않은 SEEK_HOLE
파일 시스템 에서는 작동합니다 . SEEK_HOLE
여기에 GNU 도구가 있습니다:
LC_ALL=C find . -type f ! -size 0 -printf '%S:%p\0' |
LC_ALL=C awk -v RS='\0' -F : '$1 < 1 {sub(/^[^:]*:/, ""); print}'
find
(이 답변의 이전 버전은 3.2e-05와 같이 희소성을 표현할 때 제대로 작동하지 않았습니다 . 감사합니다.@flashydave의 답변내 주목을 끌었다. 로케일 기준 대신 LC_ALL=C
10진수 기준이 필요합니다 (모든 구현이 로케일 설정을 존중하는 것은 아닙니다)..
awk
답변2
할당된 블록 수가 파일 크기보다 작을 때 파일은 일반적으로 희소합니다(여기서는 stat
Ubuntu에서 GNU를 사용하지만 다른 시스템에는 호환되지 않는 구현이 있을 수 있다는 점에 유의하십시오 stat
).
if [ "$((`stat -c '%b*%B-%s' -- "$file"`))" -lt 0 ]
then
echo "$file" is sparse
else
echo "$file" is not sparse
fi
변형 find
: (스테판에게서 훔침)
find . -type f ! -size 0 -exec bash -c '
for f do
[ "$((`stat -c "%b*%B-%s" -- "$f"`))" -lt 0 ] && printf "%s\n" "$f";
done' {} +
일반적으로 이를 쉘 스크립트에 넣은 다음 쉘 스크립트를 실행합니다.
find . -type f ! -size 0 -exec ./sparsetest.sh {} +
답변3
%S
다음 형식의 스파스 파일을 찾을 수 있습니다 find
.
# find / -type f -printf "%S\t%p\n" | gawk '$1 < 1.0 {print}'
0.0139994 /var/log/lastlog
0.959592 /usr/lib/locale/locale-archive
...
이 기사에서 발견된 내용: https://www.thegeekdiary.com/how-to-find-all-the-sparse-file-in-linux/
답변4
취약점이 파일의 어디에 있는지 알아내려고 노력하면서 작성한 짧은 스크립트는 다음과 같습니다.
#!/usr/bin/python3
import os
import sys
import errno
def report(fname):
fd = os.open(fname, os.O_RDONLY)
len = os.lseek(fd, 0, os.SEEK_END)
offset = 0
while offset < len:
start = os.lseek(fd, offset, os.SEEK_HOLE)
if start == len:
break
try:
offset = os.lseek(fd, start, os.SEEK_DATA)
except OSError as e:
if e.errno == errno.ENXIO:
offset = len
else:
raise
print(f'found hole between 0x{start:08X} and 0x{offset:08X} ({offset - start} bytes)')
if __name__ == '__main__':
for name in sys.argv[1:]:
report(name)
그러면 다음과 같이 인쇄됩니다.
$ echo -n 'a' >zeros; truncate -s $((4096*4)) zeros; test/report-holes.py zeros
found hole between 0x00001000 and 0x00004000 (12288 bytes)