2007. 11. 5. 20:23

한꺼번에 많은 파일 지우는 세가지 방법

원래 펄 사용의 주 목적이 리스트 및 파일 관리였기 때문에 다양한 요구조건에 대해서 가장 효율 적인 방법은 일일이 스크립트파일을 만드는 것 보다 awk, 나 sed 처럼 커맨드라인에서 바로 코드를 만드는 방법이라고 생각하고 있었다.  덕분에 프로그램을 만들때 조금만 길이기 길어져도 헤매는 부작용이 생기기는 했지만.

그 전까지는 그냥 상상력에 의존하여 나름 필요한 코드를 만들어오곤 했었는데 다음 코드를 보고는 그 포스에 감동해버렸다.
find ./ -name "*.bak" -type f| perl -nleunlink  # 코드 1
현재 디렉토리 아래의 모든 *.bak파일을 지우는 코드.

한 디렉토리에 지워야 할 파일이 매우 많을때(1024개 이상?)
rm -f *.bak        # 코드 2
는 작동하지 않는다. 이때 위의 perl 코드1은 잘 동작한다.(물론 코드1은 하위디렉토리까지 검색한다는 차이는 있다.)
 perl이외에도 방법은 있다.
find ./ -name "*.bak" -type f -exec rm -f \{\} \;       #코드3
find ./ -name "*.bak" -type f | xargs rm -f                   #코드4
코드3의 문제는 모든 파일마다 rm을 실행하므로 매우 느리다는 데 있다.
코드4의 문제는 xargs를 이용하기 때문에 rm을 호출하는 횟수가 더 적어진다.
코드1의 경우 단 하나의 perl 프로세스를 이용하여 파일을 지우기 때문에 이방법이 가장 빠를 것으로 예상할 수있다.

사실 코드4의 xargs 가  코드1의 perl보다 그리 느릴꺼라고 생각하지는 않는다. 적어도 한 프로세스로 100개이상의 파일을 처리할 수 있다면 소모되는 시간은 파일을 삭제 하는데 걸릴 시간이기 때문이다. 게다가 코드1은 사실상 perl의 아름다움을 보여주기 위하여 좀 과장된 측면이 있다. 예를 들어 처리중에 지우지 못하는 파일이 있어도, 혹은 아예 없는 파일이 리스트에 주어져도 아무런 경고를 내지 않는다. 이를 해결하기 위해서 우리는 "die" 나 "print" 또는 "warn"등의 구문을 추가해야한다.
find ./ -name "*.bak" -type f | perl -nle'unlink or die"Can't remove $_ : $!"'
빠른 방법이라고는 하지만 이제 코드쓰기가 매우 귀찮아졌다. 나라도 xargs가 쓰고싶어 질 것이다. (실제로 그러고 있다.) 하지만 반대로 생각해볼 수 있다. 지우지 못하는 파일에대한 경고를 추가했던 것처럼 우리는 필요한 무엇이든 추가할 수 있다. 텍스트 파일만 지워보자.
find ./ -name "*.bak" -type f | perl -nle'-T and unlink or print "Can't remove $_ : $!"
 find 의 옵션들을 perl로 옮겨 더욱 강력하게 만들 수도 있다.
find | perl -nle '/\.bak$/ && -f && -T and unlink or print "Can't remove $_ : $!"
(파일 테스트 연산자가 제대로 맞는지 잘 기억이...)
(주의: && and 등의 연산자가 헷갈린다면 언제나 괄호와 if 가 우리 앞에 있음을 있지 말자)

정말 지워야할 파일이 많을 수록. 지워야 할 파일을 선택하는데 기준이 복잡할 수록, 위의 코드 한줄이 점점 짧게 보일 것이다.

'Perl Recipe' 카테고리의 다른 글

두 문자열에서 중복되는 부분 찾기  (0) 2009.03.25
일전한 글자수의 단어 세기  (7) 2009.03.24
원라인 펄 놀이 - 첫줄 빼고 sort  (0) 2008.04.17
여러파일을 sorting 하기  (0) 2007.12.11
리스트 비교  (0) 2007.11.06