| -1,24 +1,349 |
| 화일 관련 연산자. |
| * -e 존재하는가? |
| * -z 크기가 0인가? |
| * -s 화일크기가 0이 아닌가? (파일의 크기 리턴) |
| * -f regular file |
| * -d directory |
| * -T 텍스트 화일 |
| * -B 바이너리 화일 |
| * -M 화일이 생성된 지 몇일이 지났는가? (0부터) |
|
| 화일입출력 |
| * open( fileHandle, "filename" ); 로 열고, |
| ** "<화일명" , "화일명" : 읽기모드 |
| ** ">화일명" : 쓰기모드 |
| ** ">>화일명" : 추가모드 |
| ** "+<화일명" : 읽기, 쓰기 |
| <toc> |
|
| == # 기본적인 입출력 == |
| * open FILEHANDLE, MODE, EXPR |
| ** EXPR 은 주로 파일명 |
| ** MODE |
| *** <code><</code> 또는 없음 : 읽기모드 |
| *** <code>></code> : 쓰기모드. 파일이 존재할 경우 내용을 지움 |
| *** <code>>></code> : 추가모드. 파일이 존재할 경우 마지막에 내용을 추가함 |
| *** <code>+<</code> : 읽기, 쓰기 |
| *** <code>+></code> : 읽기, 쓰기. 파일이 존재할 경우 내용을 지움 |
| *** <code>+>></code> : 읽기, 추가하기 |
| *** <code>|-</code> : 출력 파이프 |
| *** <code>-|</code> : 입력 파이프 |
| ** open에 실패하면 $! 변수에 에러 내용이 담긴다. |
| * 읽거나 쓰고 |
| ** @allLine = <fileHandle>; 화일 전부를 읽기 |
| ** @allLine = <fileHandle>; 파일 전부를 읽기 |
| ** $aLine = <fileHandle>; 한 줄 읽기 |
| ** print fileHandle "안녕"; 출력 |
| * close( fileHandle ); 로 닫는다. |
|
| 한 줄씩 읽는 예제: |
| {{{#!vim perl |
| open my $fileHandle, "<", $fileName ) or die "Cannot open $fileName: $!"; |
| while( $aLine = <$fileHandle> ) |
| { |
| print $aLine; |
| } |
| close $fileHandle; |
|
| # 변수를 생략하면 $_ 사용 |
| while (<$fileHandle>) { # (defined ($_ = <$fileHandle>)) |
| print "$_"; |
| } |
| }}} |
|
| 배열 변수를 써서 통채로 읽는 예제: (파일이 크면 메모리를 많이 소모할 수 있으므로 주의) |
| {{{#!vim perl |
| open my $fileHandle, "<", $fileName or die "Cannot open $fileName: $!"; |
| @allLines = <$fileHandle>; |
| close $fileHandle; |
| }}} |
|
| "input record separator" 변수 $/의 값을 바꿈으로써 스칼라 변수에 파일 전체를 담는 경우. ($/의 기본값은 "\n") |
| {{{#!vim perl |
| local $/ = undef; |
| open my $fileHandle, "<", $fileName or die "Cannot open $fileName: $!"; |
| $allLines = <$fileHandle>; |
| close $fileHandle; |
| }}} |
|
|
| 파일을 통채로 읽거나 쓰는 것은 Cpan:File::Slurp 모듈을 쓰면 편하다. |
|
|
| === # 읽기쓰기 모드에서 읽기와 쓰기의 전환 === |
|
| "+<", "+>", "+>>" 를 사용하여 열 경우에, 읽는 동작과 쓰는 동작을 번갈아가며 수행할 경우 예상치 않은 결과가 나올 수 있다([http://cafe.naver.com/perlstudy/1244 예]) 읽기와 쓰기 동작 사이에는 <code>seek</code>를 써서 제대로 파일포지션 포인터를 세팅해 주어야 하는 듯. |
|
|
|
| === # chomp === |
| 스트링 뒤의 new line "\n"을 제거<footnote(Learning Perl, Chapter 03)> 정확히는, $/변수의 값을 제거<footnote([http://japhy.perlmonk.org/articles/misc/files.html Just Another Perl Article])> |
| {{{#!vim perl |
| $line = <STDIN>; |
| chomp $line; |
| # 한 줄로 |
| chomp ($line = <STDIN>); |
|
| ## 리스트의 경우는, 각 엘리먼트의 "\n"을 일괄 제거 |
| chomp (@lines = <STDIN>); |
| }}} |
|
| === # 인자 3개 형태의 open을 쓰자 === |
|
| 파일명에 잘못된 문자(부등호 등)가 포함되거나, 악의적으로 파이프 등을 사용하는 것에 대비해서, 인자 3개 형태로 사용하자. |
| {{{#!vim perl |
| open FH, $filename; # 이건 위험 |
| open FH, "< $filename"; # 입력의 경우 "<"가 없어도 되지만 명시하는게 안전 |
| # perl 5.6 이상부터는 별개의 인자로 줄 수 있음 |
| open FH, "<", $filename; # 이것을 권장 |
| }}} |
|
|
|
| === # 파일핸들도 렉시컬 변수를 쓸 수 있다 === |
|
| {{{#!vim perl |
| open FH, "<", $filename; # FH 는 전역적인 파일핸들 |
| open my $fh, "<", $filename; # $fh 는 렉시컬 변수. 권장 |
| }}} |
|
|
|
|
|
| == # <ARGV> == |
| <code><ARGV></code>또는 <code><></code> - 명령행 인자로 들어온 스트링을 파일명으로 취급하여 모든 파일들을 열고 읽음. 인자가 없으면 표준입력을 읽음. |
|
| 현재 읽고 있는 파일의 이름은 $ARGV 에 담긴다. |
|
| {{{#!vim perl |
| #!/usr/bin/perl |
| # nl3.plx |
| use warnings; |
| use strict; |
|
| my $lineno; |
| my $current = ""; |
|
| while (<>) { |
| if ($current ne $ARGV) { |
| $current = $ARGV; |
| print "\n\t\tFile: $ARGV\n\n"; |
| $lineno=1; |
| } |
|
| print $lineno++; |
| print ": $_"; |
| } |
| }}} |
|
| == # $/ == |
| * $/ = ""; - blank line을 구분자로 함 (단락 단위로 읽는다고 볼 수 있다) |
| * $/ = undef; - file 내용 전체를 하나의 스칼라로 읽음 |
| * $/ = \1024; (양수의 레퍼런스) - 한 번에 1024바이트를 읽음<footnote([http://japhy.perlmonk.org/articles/misc/files.html Just Another Perl Article])> |
| * chomp 의 역할은 인자의 제일 뒤에 $/ 변수의 값이 있는 경우 그것을 제거<footnote([http://japhy.perlmonk.org/articles/misc/files.html Just Another Perl Article])> |
| == # 파일 핸들끼리의 할당 == |
| {{{#!vim perl |
| if (defined $input) { |
| open INPUT, $input or die "Couldn't open file $input: $!\n"; |
| } else { |
| *INPUT = *STDIN; # typeglob을 사용해야 함 |
| } |
| }}} |
|
| === # 파일 핸들을 서브루틴의 인자로 넘기기 === |
| {{{#!vim perl |
| # typeglob 사용 |
| sub say_hello { |
| *WHERE = shift; |
| print WHERE "Hi there!\n"; |
| } |
| say_hello(*STDOUT); |
|
| ## 또는 |
| sub say_hello { |
| my $fh = shift; # 일반 변수에 |
| print $fh "Hi there!\n"; |
| } |
| say_hello(*STDOUT); # 호출하는 쪽에서는 typeglob |
| }}} |
|
| == # 바이너리 파일 입출력 == |
| {{{#!vim perl |
| binmode FILEHANDLE; |
| }}} |
|
| == # select == |
| <code>write</code>나 <code>print</code> 등 출력에 사용되는 디폴트 파일 핸들을 지정하며, 현재의 디폴트 파일 핸들을 반환한다. |
|
| {{{#!vim perl |
| select LOG; |
| print "blah blah...\n"; # LOG에 해당하는 파일로 출력된다. |
|
| select STDOUT; # 표준출력으로 복원 |
| }}} |
|
| == # 버퍼링 == |
| select 로 지정된 파일핸들에 대하여 |
| * $| = 0; - 운영체제의 버퍼링 사용 (기본값) |
| * $| = 1; - 버퍼링 사용하지 않음 |
| {{{#!vim perl |
| $| = 1; |
| for (1...20) { |
| print "."; # 버퍼링이 사용될 경우, 20초 후에 한꺼번에 20개의 "."이 출력된다. |
| sleep 1; |
| } |
| print "\n"; |
| }}} |
|
| [http://perl.plover.com/FAQs/Buffering.html Suffering from Buffering?] 글도 참고 |
|
|
|
| == # 디렉토리 == |
| === # chdir === |
| chdir - working directory 변경<footnote(Learning Perl, Chapter 11)> |
| * 변경된 디렉토리는 자식 프로세스에 상속됨 |
| * 파라메터가 생략되었을 경우는 '''$_을 쓰는 게 아니라''' 현재 사용자의 홈 디렉토리로 변경 시도 |
| * 쉘의 cd에서 가능한 ~username 형식은 지원하지 않는다. - 이것은 OS가 아니라 쉘의 기능 |
|
| === # Globbing === |
| Globbing - 파일명 패턴 확장<footnote(Learning Perl, Chapter 11)> |
| {{{#!vim perl |
| my @all_files = glob "*"; |
| my @pm_files = glob "*.pm"; |
| my @all_files_including_dot = glob ".* *"; # 패턴들은 공백으로 구분 |
| # 또는 |
| my @all_files = <*>; |
| }}} |
|
| === # Directory Handle === |
| opendir로 열고, readdir로 읽고, closedir로 닫는다<footnote(Learning Perl, Chapter 11)> |
| * readdir의 리턴값은 경로명을 제외한 파일명만 들어 있으니 주의 |
| {{{#!vim perl |
| opendir DH, "." or die "Couldn't open the current directory: $!"; |
| while ($_ = readdir(DH)) { # readdir은 파일명을 하나씩 반환 |
| next if $_ eq "." or $_ eq ".."; |
| print $_, " " x (30-length($_)); |
| print "d" if -d $_; |
| print "r" if -r _; # "_"는 "마지막으로 테스트한 파일"을 의미 |
| # ... |
| } |
| closedir DH; |
| } |
| }}} |
|
| == # 파일 관련 테스트 연산자 == |
| 파일 속성 테스트 연산자들<footnote(Learning Perl, Chapter 11)> |
| |< File test |< Meaning || |
| |< -r |< File or directory is readable by this (effective) user or group || |
| |< -w |< File or directory is writable by this (effective) user or group || |
| |< -x |< File or directory is executable by this (effective) user or group || |
| |< -o |< File or directory is owned by this (effective) user || |
| |< -R |< File or directory is readable by this real user or group || |
| |< -W |< File or directory is writable by this real user or group || |
| |< -X |< File or directory is executable by this real user or group || |
| |< -O |< File or directory is owned by this real user || |
| |< -e |< File or directory name exists || |
| |< -z |< File exists and has zero size (always false for directories) || |
| |< -s |< File or directory exists and has nonzero size (the value is the size in bytes) || |
| |< -f |< Entry is a plain file || |
| |< -d |< Entry is a directory || |
| |< -l |< Entry is a symbolic link || |
| |< -S |< Entry is a socket || |
| |< -p |< Entry is a named pipe (a "fifo") || |
| |< -b |< Entry is a block-special file (like a mountable disk) || |
| |< -c |< Entry is a character-special file (like an I/O device) || |
| |< -u |< File or directory is setuid || |
| |< -g |< File or directory is setgid || |
| |< -k |< File or directory has the sticky bit set || |
| |< -t |< The filehandle is a TTY (as reported by the isatty( ) system function; filenames can't be tested by this test) || |
| |< -T |< File looks like a "text" file || |
| |< -B |< File looks like a "binary" file || |
| |< -M |< Modification age (measured in days) || |
| |< -A |< Access age (measured in days) || |
| |< -C |< Inode-modification age (measured in days) || |
|
| == # stat, lstat == |
| 심볼릭 링크의 경우 stat은 링크가 가리키는 파일에 대한 정보를 얻어온다. 링크 자체의 정보를 얻고 싶다면 lstat을 사용<footnote(Learning Perl, Chapter 11)> |
| {{{#!vim perl |
| my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, |
| $size, $atime, $mtime, $ctime, $blksize, $blocks) |
| = stat($filename); |
| }}} |
|
| == # special underscore filehandle == |
| 동일한 파일에 여러 번 파일 테스트 연산자,stat,lstat 연산을 수행하는 경우, "_"를 인자로 주면 기존 연산 시 얻어온 정보를 재사용한다. (서브루틴 등에서 stat을 부르는 바람에 자신도 모르는 사이에 대상 파일이 바뀌었을지 모르니 주의)<footnote(Learning Perl, Chapter 11)> |
| {{{#!vim perl |
| push @big_old_files, $_ |
| if (-s) > 100_000 and -A _ > 90; # -A 의 인자로 "_" |
| }}} |
|
|
| 참고: <code>-l _</code>의 경우는 가장 최근에 파일 정보를 얻어온 방법이 <code>lstat</code>이어야만 의미가 있다. <code>stat</code>은 심볼릭 링크의 경우 실제 타겟 파일을 찾아가서 정보를 얻어오므로 -l 연산의 결과가 결코 참이 되지 않기 때문이다. 직전에 수행한 게 lstat 이 아닐 경우 "The stat preceding -l _ wasn't an lstat"라는 에러가 난다.<footnote([http://www.learning-perl.com/?p=395 “The stat preceding -l _ wasn’t an lstat” | Learning Perl])> |
|
|
|
| == # 파일, 디렉토리 관련 명령어와 함수 == |
| * rename OLDNAME, NEWNAME |
| * unlink LIST |
| {{{#!vim perl |
| $cnt = unlink ’a’, ’b’, ’c’; |
| unlink @goners; |
| unlink <*.bak>; |
| }}} |
| * link OLDFILE, NEWFILE - 하드 링크 |
| * symlink OLDFILE, NEWFILE - 심볼릭 링크 |
| ** readlink EXPR - 심볼릭 링크의 값을 읽음 |
|
| * mkdir FILENAME, MASK |
| * rmdir FILENAME |
| ** 빈 디렉토리만 삭제 가능 |
| ** File::Path 모듈의 rmtree를 쓰면 편하다 |
|
| * chmod LIST |
| ** ex) chmod 0755, "fred", "barney"; |
| * chown LIST |
| ** ex) chown $user, $group, @filenames; |
| ** user ID와 group ID는 숫자. 이름으로부터 얻고 싶다면 getpwnam, getgrnam 사용하여 해당 숫자 값을 먼저 얻을 것 |
| * utime LIST - 액세스 시각과 수정 시각 변경 |
| ** ex) utime $atime, $mtime, @filenames; |
|
|
| == # 인코딩 지정 == |
|
| 파일 입출력 Layer에서 인코딩/디코딩 변환을 지정할 수 있음<footnote([http://aero.springnote.com/pages/1053508 Unicode in Perl - aero님의 노트])> |
|
| {{{#!vim perl |
| # UTF-8로 저장된 파일을 읽어서 디코드 |
| open my $fh, '<:utf8', 'file.txt'; |
|
| # UTF-8로 저장된 파일을 읽어서 디코드 - 정합성 체크까지 |
| open my $fh, '<:encoding(UTF-8)', 'file.txt'; |
|
| # EUC-KR로 저장된 파일을 읽어서 디코드 |
| open my $fh, '<:encoding(EUC-KR)', 'file.txt'; |
|
| # UTF-8로 인코드하여 저장 |
| open my $fh, '>:utf8', 'file.txt'; |
|
| # 이미 열려 있는 파일 핸들은 binmode 로 지정 가능 |
| binmode STDIN,':utf8'; |
| }}} |
|
|
|
| == # 스트링 변수를 파일처럼 읽거나 쓰기 == |
|
| Perl 5.8 부터 지원 |
|
| {{{#!vim perl |
| my $string; |
| open my $fh, ">", \ $string; |
|
| # 위 두 줄을 아래처럼 쓸 수도 있음 |
| open my $fh, ">", \ my $string; |
|
| # 일반적으로 파일을 다루듯이 쓸 수 있음 |
| print $fh "Hello"; |
| }}} |
|
| 단, 파일 핸들과 연결되어 있는 상태의 스트링 변수에 다른 형태로 접근할 경우 의도하지 않은 결과가 나오니 주의.<footnote([http://www.effectiveperlprogramming.com/blog/770 Avoid modifying scalars connected to string filehandles | The Effective Perler])> |
|
|
|
| == # 기타 == |
|
| * [http://perl.plover.com/FAQs/Buffering.html Suffering from Buffering?] |
|
|
| == # Comments == |
|
| <longcomments(100)> |
|
|
| ---- |
| [[컴퓨터분류]] |