Perl 파일 조작과 파일 핸들러 사용 방법 예제

Perl에서는 파일 입출력 파일 핸들러라는 것이 있습니다. 파일 핸들러는 지금 어느 파일을 처리하고 있는지를 관리하기 위한 것입니다.

파일을 읽거나 쓰는 것을 하기 위해 우선 파일을 열고 파일 핸들러와 관계를 맺어줍니다.

그리고 파일 핸들러를 조작하는 것이 기본 조작법입니다.

 

표준 입출력

Perl에는 특별한 파일 핸들러로 다음과 같은 3개가 있습니다.

 파일 핸들러의미내용
 STDIN 표준 입력파이프나 리다이렉트 시에 데이터를 읽어옴.
커맨드 라인의 경우에는 키보드.
 STDOUT 표준 출력파이프나 리다이렉트 시에 데이터를 출력.
커맨드 라인의 경우에는 모니터.
 STDERR 표준 에러 에러 발생 시 출력.

 

※파이프 : 표준 출력과 표준 입력을 경유해서 데이터를 건네받는 구조로,

      이 프로그램이 표준 출력으로 출력한 결과를 다른 프로그램의 표준 입력에 건네는 구조.

※리다이렉트 : 표준 출력 그대로 텍스트 파일 등으로 써내는 방식.

예를 들어 커맨드 라인에서 조작하는 경우, 다음과 같은 스크립트 실행을 할 수 있습니다.

use strict;

# 질문
print "이름 ? \n"'

# 표준 입력
my $name = <STDIN>;

# 출력
print "안녕하세요. $name 씨 \n";

 

이처럼 키보드 입력을 표준 입력으로 하는 파일 핸들러 STDIN으로부터 변수 $name에 저장하고, 문자열을 조작, 표시할 수 있습니다.

 

open함수와 파일 핸들러

파일 핸들러 이외에도 open함수를 사용할 수 있습니다.

open함수를 사용해서 파일을 읽어오는 경우의 구문은 다음과 같습니다.

1. 파일을 읽어오기 모드로 여는 경우 (open 명령)

open 파일 핸들러, "파일명";

 

2. 파일을 읽어오는 처리 (read 명령)

배열 = <파일 핸들러>

 

3. 오픈한 파일을 닫는 처리 (close 명령)

close 파일 핸들

 

예를 들어 하나의 일련 처리로 해서, 파일을 읽고 표시하는 것으로는 다음과 같이 할 수 있습니다.

open(IN,"data.txt");	 # IN이라는 파일 핸들러로 읽어오기.
@data = <IN> ;      # 읽어온 파일을 배열 @data에 저장.

close(IN);	           # 읽기 처리를 닫음.

foreach (@data) {
	print;
}

 

단, 읽어온 파일이 대량의 데이터의 경우 위의 방법과 같이 한번에 읽어오면 위험할 때도 있습니다.

 그런 경우에는 while문을 사용해서 한 줄씩 읽어올 수 있습니다.

open(IN,"data.txt");
while(<IN>) {
    print;
}
close(IN);

 

 

파일 출력

파일에 출력하는 조작을 하는 경우에도 open함수와 파일 핸들러를 사용합니다.

open함수에 의해 파일에 출력하는 방법으로는 다음과 같은 구문이 있습니다.

구문내용
 open (FH, “file”) 읽기 모드
 open (FH, “< file”)
 open (FH, “> file”) 쓰기 모드
 open (FH, “>> file”) 추가로 쓰기 모드
 open (FH, “+< file”) 읽기쓰기 모드
 open (FH, “+> file”)
 open (FH, “+>> file”)
 open (FH, “| command”) 파이프 출력용
 open (FH, “command |”) 파이프 입력용

 

코드 예 -1 파일 읽기

open(FH, "< data.txt");
print <FH>;
close(FH);

 

data.txt을 읽어옵니다.

읽기 모드이기 때문에 data.txt 안의 내용에는 영향이 없습니다.

< 를 생략해서 open(FH, “data.txt”)로도 사용할 수 있습니다. 

 

코드 예 -2 덮어쓰기

open(FH, "> data.txt");
print FH DEF;
close(FH);

 

data.txt 파일에 [DEF]라는 문자열로 덮어쓰기를 했습니다.

덮어쓰기 때문에 data.txt 파일의 내용이 삭제되고 새롭게 쓰입니다.

 

코드 예 -3 추가로 쓰기

open(FH, ">> data.txt");
print FH XYZ;
close(FH);

 

data.txt 파일에 [XYZ]라는 문자열로 추가로 쓰기를 했습니다.

추기로 쓰기 때문에 data.txt 파일의 내용이 삭제되지 않고 추가로 쓰입니다.

 

코드 예 -4 읽기 쓰기

open(FH, "+< data.txt");
$log = ;
if ($log eq 'A') {
	print FH 'B';
}
close(FH);

 

읽기 쓰기 모드이기 때문에 읽기만 해도 되고 상관없습니다.

 

코드 예 -5 읽기 쓰기

open(FH, "+> data.txt");
print FH "ABC";
seek(FH, 0, 0)  # 포인터를 맨앞으로 이동
$data = <FH>;
close(FH);

print $data ;

 

읽기 쓰기 모드이기 때문에 쓰기만 해도 되고 상관없습니다.

 

코드 예 -6 읽기 쓰기

open(FH, "+>> data.txt");		# 해당 파일에 [ABC]라고 적혀있음
print FH "DEF";				# 추가로 쓰기
seek(FH, 0, 0)				# 포인터를 맨앞으로 이동
$data = <FH>;
close(FH);

print $data ;

 

읽기 쓰기 모드의 추가로 쓰기입니다.

 

코드 예 -7 커맨드로부터 파이프 입력용 오픈

open(IN, "ls -l |");
@cmd = <IN>;
close(IN);

foreach $cmd(@cmd) {
	print "$cmd \n";
}

 

ls -l라는 커맨드를 실행하고 그 결과를 배열 @cmd에 저장합니다.

 

코드 예 -8 커맨드에 파이프 출력용 오픈

open(OUT "| /usr/sbin/senmail");
print(OUT) "HELLO";
close(OUT);

 

sendmail이라는 외부에 있는 소프트 웨어에 HELLO라는 커맨드를 출력합니다.

 

파일 삭제와 변경

그 외에 파일 조작을 하기 위한 함수로는 다음과 같은 것이 있습니다.

내용구문
 파일 삭제 unlink 파일명
 파일명 변경 rename 변경전 파일명, 변경후 파일명
 권한 변경 chmod 모드, 파일1,파일2,…파일n

 

코드 예 -1 unlink함수

# file.txt를 삭제
unlink("file.txt");

 

코드 예 -2 rename함수

# file.txt를 data.txt로 파일명 변경
rename("file.txt", "data.txt");

 

코드 예 -3 chmod함수

 # file.txt의 권한을 666으로 변경
chmod(0666, "file.txt");

 

chmod함수의 첫 번째 인수로 지정하는 [모드]는 위의 예처럼 맨 앞에 0을 붙입니다.

이것은 지정하는 권한 값을 10진법으로 사용한다는 의미입니다.

그리고 chmod함수는 한 번에 여러 개의 파일의 권한을 변경할 수 있습니다.

이러한 경우에는 다음과 같이 변경할 파일 이름을 여러 개 작성하면 됩니다.

 

코드 예 -4 chmod함수

# 여러개의 파일 권한을 666으로 변경
chmod(0666, "file.txt", "data.txt", "log.txt");

 

 

파일 복사와 이동

파일을 복사하는 경우 Perl에는 함수가 없습니다.

그러기 때문에 open함수를 사용하는 방법과 Perl모듈을 사용하는 2가지 방법이 있습니다.

우선은 open함수를 사용해보겠습니다.

 

코드 예 -1 open함수

use strict;

my $old = 'old.txt';
my $new = 'new.txt';

open(OLD,"$old");
open(NEW,"> $new");
while(<OLD>) {
    print NEW $_;
}
close(OLD);
close(NEW);

print "OK\n";

 

적은 양의 데이터 파일이라면 위와 같은 방법으로도 충분합니다.

하지만 사진이나 대량의 파일을 복사하는 경우를 고려한다면, 일정 사이즈로 읽어오는 방식이 좋을 거 같습니다.

다음과 코드 예는 read함수를 병용한 것입니다. 1024바이트씩 읽어 와서 복사하고 있습니다.

그리고 binmode함수는(8,9행) 윈도우 환경에서 바이너리 파일을 취급하는 경우를 고려한 것입니다.

 

코드 예 -2 open함수

use strict;

my $old = 'old.jpg';
my $new = 'new.jpg';

open(OLD, "$old");
open(NEW, "> $new");
binmode(OLD);
binmode(NEW);
while ( read( OLD, my $buf, 1024 ) ) {
	print NEW $buf;
}
close(OLD);
close(NEW);

print "OK";

 

다음으로, 모듈을 이용해보도록 하겠습니다.

Perl모듈로 File::Copy모듈이 있습니다. 

 

코드 예 -3 File::Copy모듈

use strict;
use File::Copy;

my $old = 'old.jpg';
my $new = 'new.jpg';

copy($old, $new);

print "OK";

 

File::Copy모듈은 파일 이동도 가능합니다.

 

코드 예 -4 File::Copy모듈(이동)

use strict;
use File::Copy;

my $old = 'old.jpg';
my $new = 'new.jpg';

move($old, $new);

print "OK";

 

File::Copy모듈을 이용 가능한 서버 환경에서는 File::Copy모듈을 이용하는 것이 편합니다.

 

디렉토리 복사 및 삭제

단순히 파일을 복사하는 법을 위에서 보았습니다.

이번에는 디렉토리 안에 있는 파일과 디렉토리를 복사하는 것에 대해 살펴보도록 하겠습니다.

opendir + File::Copy 조합으로도 가능하지만 소스가 조금 길어집니다.

그래서 소개할 모듈은 File::Copy::Recursive모듈 입니다.

단, 아쉽게도 표준 모듈이 아니기 때문에, 각자 인스톨이 필요합니다.

사용법은 다음과 같습니다.

 

코드 예 -1 File::Copy::Recursive 복사

use strict;
use File::Copy::Recursive qw(rcopy);

my $old = './old'; 
my $new = './new';

rcopy($old, $new);

print "OK";

 

예제를 보면 rcopy에 의해 old디렉토리 안에 모든 파일과 디렉토리가 new디렉토리 안으로 복사됩니다.

그리고 각 디렉토리와 파일의 권한도 적용해줍니다.

다음으로는 삭제하는 방법을 살펴보겠습니다.

삭제는 File::Path모듈을 이용합니다.

 

코드 예 -2 File::Path 삭제

use strict;
use File::Path;

my $dir = './dir';

rmtree($dir);

print "OK";

 

위에 rmtree에 의해 dir디렉토리 안의 모든 파일과 디렉토리가 삭제됩니다.

그리고 rmtree는 반환값을 돌려주기 때문에 삭제한 파일과 디렉토리의 개수를 알 수 있습니다.

 

코드 예 -3 File::Path 삭제(반환값 확인)

use strict;
use File::Path;

my $dir = './dir';

my $num = rmtree($dir);

print "$num개를 삭제 했습니다.";

댓글

  1. perl연습생 댓글:

    한국에 있는 일본계 회사 재직중입니다.
    perl라고 한국에서는 생소한 ㅜㅜ 언어로 많은 스크립트가 있는 회사인데..
    대부분 예전에 만든 프로그램들인데 다 퇴사한지라.. 배울 사람도 없고 조금이나마 수정이라도 해보려고
    언어를 배워보려하는데 벽이 많네요 비전공인지라

    포스팅글 정말 감사하게 봤습니다.

    궁금한 내용 있다면 질문드려도 될런지요?