@gypark - gypark.pe.kr의 주인장. 홈페이지에 Perl에 대해 정리해두는 취미가 있고, Raymundo라는 닉을 사용하기도 한다.
어떤 디렉토리의 용량, 즉 그 디렉토리 안에 있는 파일들과 서브디렉토리들이 차지하는 용량의 총합이 얼마나 될까 궁금하면 어떡해야 할까요? File::Find 모듈을 사용해서 서브디렉토리를 재귀적으로 탐색하며 모든 파일들을 찾으면서, 각 파일들의 크기를 구해서 더하면 되겠죠! 아니면 qx()를 사용하여 유닉스/리눅스 명령어인 du를 실행한 후 출력으로 나온 문자열을 정규식을 써서 해석하면 되겠지요.
디스크 전체의 사용량과 남은 용량이 궁금하다면 어떡해야 할까요? 이번에도 리눅스 명령어인 df를 실행해 나온 출력을 갈무리한 후 정규식을 써서 원하는 부분을 추출하면 됩니다.
흠...
전부 맘에 들지 않는다는 까다로운 사람들을 위해, 다른 방법을 알아봅시다.
필요한 모듈은 다음과 같습니다.
직접 CPAN을 이용해서 설치한다면 다음 명령을 이용해서 모듈을 설치합니다.
$ sudo cpan \ Filesys::DiskUsage \ Filesys::DfPortable
사용자 계정으로 모듈을 설치하는 방법을 정확하게 알고 있거나 perlbrew를 이용해서 자신만의 Perl을 사용하고 있다면 다음 명령을 이용해서 모듈을 설치합니다.
$ cpan \ Filesys::DiskUsage \ Filesys::DfPortable
다음과 같이 사용합니다.
use utf8; use strict; use warnings; use Filesys::DiskUsage qw/du/; # 특정 파일이나 디렉토리의 용량 my $usage = du( '/Users/gypark/local/eclipse' ); # 여러 파일과 디렉토리의 용량 합 my $total = du( qw(file1 dir1 dir2) ); # 합 대신 각 용량들의 배열을 얻으려면 my @sizes = du( qw(file1 dir1 dir2) ); # 각 대상과 용량을 짝지은 해시를 얻으려면 my %sizes = du( { 'make-hash' => 1 }, qw(file1 dir1 dir2) ); # %sizes = ( # file1 => ..., # dir1 => ..., # dir2 => ... # )
다만 이 모듈을 통해 얻어낸 값은, 셸에서 du
명령어를 써서 얻어낸 값과 정확히 일치하지는 않습니다.
셸의 du
명령어는 파일이 실제로 차지하는 디스크 블록의 크기를 출력하는데,
Filesys::DiskUsage
모듈이 파일의 크기를 계산할 때는 파일 자체의 바이트 크기를 가져오기 때문입니다.
자신이 사용하는 디스크의 할당 블록 크기는 다음과 같이 알 수 있습니다.
# 리눅스: blockdev --getbsz <검사하려는 장치> # blockdev --getbsz /dev/mapper/VolGroup00-LogVol00 4096 # MacOSX: diskutil info <장치> $ diskutil info / | grep 'Block Size' Device Block Size: 512 Bytes Allocation Block Size: 4096 Bytes
위의 경우는 리눅스와 맥 다 4096바이트를 기본 할당 블록의 크기로 사용하고 있습니다.
즉 우리가 1바이트짜리 파일을 만들어도, 그 파일은 디스크에서 4096바이트를 차지하게 됩니다.
이 값을 반영하고 싶으면 sector-size
옵션을 명시합니다.
my $alloc_size = du( { 'sector-size' => 4096 }, 'file1' );
이외에도 여러 옵션이 있습니다. 자세한 것은 모듈 문서를 참고하세요.
다음과 같이 파일시스템의 전체 정보를 얻을 수 있습니다. 다음 코드는 모듈 문서에 있는 거의 그대로입니다.
use utf8; use strict; use warnings; use Filesys::DfPortable; my $ref = dfportable('/'); if ( defined($ref) ) { print "전체 바이트 : $ref->{blocks}\n"; print "미사용 바이트 : $ref->{bfree}\n"; print "가용 바이트 : $ref->{bavail}\n"; print "사용 바이트 : $ref->{bused}\n"; print "사용 퍼센테이지: $ref->{per}\n" }
실행 결과는 다음과 같은 식입니다.
$ perl df.pl 전체 바이트 : 19632164864 미사용 바이트 : 4333805568 가용 바이트 : 3320463360 사용 바이트 : 15298359296 사용 퍼센테이지: 82
"미사용 바이트"와 "가용 바이트"가 따로 있고, 이 값은 서로 같지 않을 수 있습니다. 사용자 별로 디스크 쿼터가 할당되어 있거나 하면 자신이 쓸 수 있는 가용 바이트는 미사용 바이트보다 작아질 것입니다.
$ref
해시 레퍼런스의 각 키에 해당하는 값들은({per}
를 제외하고) 기본 단위가 블록의 개수입니다.
그런데 한 블록 당 1바이트라고 상정한 상태에서 계산이 되므로, 결과적으로는 단위가 바이트인 것과 같습니다.
dfportable()
함수의 두 번째 인자로 블록 크기를 지정해줄 수 있습니다.
use Filesys::DfPortable; my $ref = dfportable('/', 1024); # 1KB print "1KB 블록의 개수 : $ref->{blocks}\n";
"1KB 블록의 개수"란 것은 결국 크기를 KB 단위로 쓴 것과 같겠죠?
이 외에도 아이노드의 전체 개수, 사용 중인 아이노드의 개수 등을 알 수도 있습니다. 단 파일시스템에서 지원하는 경우에만 그렇습니다. 자세한 것은 모듈 문서를 참고하세요.
물론 외부 명령을 이용해서도 디렉터리나 디스크 사용량을 알아낼 수 있고, 또 쉘 스크립트를 사용한다면 선택의 여지는 별로 없겠죠. 하지만 때에 따라서는 외부 프로세스를 실행하는 것이 불가능한 내부적 또는 외부적 이유가 있을 때도 있죠. CPAN의 Filesys::DiskUsage 모듈과 CPAN의 Filesys::DfPortable 모듈을 사용한다면 더이상 외부 명령어를 실행하고 그 출력을 정규식을 써서 추출하지 않아도 됩니다. 스크립트의 수행 속도가 빨라지는 것은 덤이랍니다. :-)
X-mas tree
& Llama
ASCII Art by ASCII Art Farts.
Computer ASCII Art by Chris.com.
Font ASCII Art by ASCII Art Farts.
Text ASCII Art by patorjk.com.
Artwork by
Inkyung Park
& Keedi Kim.
Designed by
Hojung Youn
& Keedi Kim.
Articles by
Seoul Perl Mongers.
Edited by
Keedi Kim.
Hosting sponsored by
SILEX.
Sponsored by
SILEX.
.-''' __ __ / \/ \/ \ =-_- | \. -____- / \ // /|| '' //| //|| == = == ==