2007년 3월 13일 화요일
쉘 스크립트 활용 - 검색하여 찾은 파일 삭제
해서 생각해보니 우리의 만능 맨 쉘이 있었으니~~
[code type=bash]listFile=`find . -name "*.txt" -print`
for i in `echo $listFile`
do
rm $i
done[/code]
요렇게 하면된다~ 정말 쉽죠~?
2006년 10월 31일 화요일
Cron ....
■ CRON
→ 같은 작업을 주기적으로 반복할수 있도록 해준다.
보통 /etc/rc.d/init.d/crond 데몬에 의해 실행된다.
설정은 /usr/bin/crontab 명령어를 사용한다.
♠ 관련명령어 및 파일
1.crontab
▶ cron작업을 설정하는 명령이다. 실행시키면 기본vi편집기가 실행된다.
▶ option
-l : 현재 crontab 에 의해 설정된 내용을 출력한다.
-e : crontab 의 내용을 작성하거나 수정한다.
-r : crontab 의 내용을 삭제한다.
-u : root권한자가 해당사용자의 crontab 파일을 다룰때 사용한다.
▶ 예제
[root@linux root]#crontab -l
→ 작업목록을 보여준다.
[root@linux root]#crontab -e -u bluetree
→ bluetree 사용자의 crontab 을 작성하거나 수정한다.
[root@linux root]#crontab aaa
→ aaa 란 파일을 crontab 으로 사용한다.
aaa 에는 이미 crontab 형식에 맞에 입력되어 있어야한다.
▶ crontab 의 작업형식
→ 5개의 날짜필드와 1개의 명령필드로 구성되어있다.
MM HH DD mm d command
MM : 분을 의미한다 ( 0 ~ 59까지 사용)
HH : 시를 의미한다. ( 0 ~ 23 까지 사용)
DD : 날짜를 의미한다 ( 1 ~ 31까지 사용)
mm : 달을 의미한다.( 1 ~ 12까지 사용)
d : 요일을 의미한다.( 0 ~ 7 까지 사용, 0 과 7은 일요일을 나타낸다)
command : 실행할 명령을 입력한다.
※ 참고
위 형식에서 시간을 나타내는 각 필드에서 와일드 카드 '*'를 사용할수 있고
각각의 요일을 구분할 때 ',' 를 사용하고 연일을 나타낼때는 '-'를 사용한다.
즉 월요일과 수요일은 '1,3' 월요일부터 금요일까지는 '1-5' 로 표시할수있다
2./etc/crontab
→ 시스템이 정기적인 작업이 수행될수 있도록 기본적으로 설정되어있는 파일이다.
3./var/spool/cron 디렉토리
→ 각각의 사용자가 등록한 crontab은 이 디렉토리아래에 각 사용자이름으로 저장된다.
♠ crontab 내용 설정예
0 12 * * 1-5 /home/bluetree/start
→ 월요일부터 금요일까지 /home/bluetree/start 란 스크립트를 실행시킨다.
0 12 1 1-12/2 * /home/bluetree/babo
→ 1월부터 12월까지 2개월마다 /home/blutree/babo 란 화일을 실행시킨다.
0 4 * * 1,3,5 cat /root/notice | mail -s "notice" bluetree75@naver.com
→ 월,수,금 오전 4시에 notice 라는 문서의 내용을 메일로 발송한다.
♠ cron 사용자 제한
※ /etc/cron.allow (허가목록) 과 /etc/cron.deny(거부목록) 을 참조하게된다.
1./etc/cron.deny 만 존재하는경우
→ 기본적으로 모든사용자가 사용가능하고 cron.deny 에 등록된 사용자만
사용불가능하다.
2./etc/cron.allow 만 존재하는 경우
→ cron.allow 파일에 등록된 사용자만 사용가능하다.
3. 두 파일 모두 없을경우
→ 모든 사용자가가능하다
4. 두 파일 모두 있을경우
→ cron.deny 내용을 무시하고 cron.allow 명기된 사용자만 사용가능하다
(출처 : 'LINUX 스케쥴링 CRON' - 네이버 지식iN)
2006년 10월 13일 금요일
Regular Expressions.. 정규식..
잃어버리기 전에 하나씩 메모..
^ 는 라인의 제일 처음을 말한다.
$ 는 정규식에서 라인의 제일 마지막을 말한다. (주위 : 원래 ^, $ 는 정규식에서 데이터의 시작과 끝을 의미)
| 는 and를 의미한다. 이 기호의 양쪽에 있는 두 글자를 모두 찾습니다. (ex. java|jsp|servlet)
\t 탭 문자를 찾습니다.
\n 줄 바꿈 문자를 찾습니다
. 모든 문자를 찾습니다.
[] 대괄호 범위의 모든 문자를 찾습니다. (ex. "[ab]" 는 "a"와 "b"를 모두 찾습니다. "[a-z]" a부터 z까지입니다.)
- 한글검색: 한글의 범위는 "ㄱ-ㅎ, 가-힣" 입니다.
[^] 대괄호 범위의 모든 문자를 제외한 문자를 찾습니다. (ex. "[^a-z]" a~z까지의 문자를 제외합니다.)
- 주의: 괄호안에서 ^와 괄호밖에서 ^의 용도를 잘 생각하라..
* 0번 또는 그 이상의 문자를 찾습니다. (ex. "j[a*]" 는 java, jad ... 의 ja를 검색합니다.)
() 식을 해석하는 순서를 바꾸거나 식을 태그로 표시할 때 사용합니다.
참고.. (http://blog.naver.com/satmania?Redirect=Log&logNo=90008546174)
"ab*" a뒤에 0 이상의 b가 있는 문자열 ("a", "ab", "abbb", 등)
"ab+" 위와 동일 하지만 최소한 하나 이상의 b가 있어야 함 ("ab", "abbb", 등)
"ab?" b가 하나 있을 수도 있고 없을 수도 있음 (ab 또는 a)
"ab{2}" a뒤에 2개의 b가 있는 문자열 ("abb"); "ab{2,}" a뒤에 최소한 2개 이상의 b가 있는 문자열 ("abb", "abbbb", 등.); "ab{3,5}" a뒤에 3개에서 5개 사이의 b가 있는 문자열 ("abbb", "abbbb", 또는 "abbbbb").
{ }를 사용할 대는 반드시 첫 번째 숫자는 적어야 됨을 유의합니다. ((O) "{0,2}", (X) "{,2}"). 또한 '*', '+', '?'는 각각 "{0,}", "{1,}", "{0,1}"와 같습니다.
이제 ()를 사용해서 하나의 문자가 아닌 여러 문자를 지정하는 방법을 알아봅니다.
"a(bc)*": a 뒤에 "bc"가 0또는 그이상의 수만큼 있는 문자열
"a(bc){1,5}": a 뒤에 "bc."가 1에서 5번 들어 있는 문자열
또 다른 특수문자로는 OR 연산을 하는 '|'를 들 수 있습니다.
"hi|hello": "hi"나 "hello"가 들어 있는 문자열
"(b|cd)ef": "bef" 또는 "cdef"
"(a|b)*c": a와 b가 섞여서 여러번 나타나고 그뒤에 c가 붙어있는 패턴
'.' (period)는 어떤 한 문자를 의미합니다.
"a.[0-9]": a뒤에 한 문자와 숫자가 붙어 있는 패턴
"^.{3}$": 3문자로만 되어 있는 문자열
[]표현은 문자열의 해당 위치에 사용될 수 있는 문자를 표현하는데 사용합니다.
"[ab]": a또는 b ("a|b"와 동일한 표현);
"[a-d]": 소문자 'a'에서 'd'까지 ("a|b|c|d"또는 "[abcd]"와 동일);
"^[a-zA-Z]": 영문자로 시작하는 문자열
"[0-9]%": % 문자 앞에 하나의 문자가 붙어 있는 패턴
",[a-zA-Z0-9]$": 영문자, 숫자로 끝나는 문자열 패턴
[]에서 '^'를 표현의 가장 처음에 사용하면 나타나서는 안 되는 문자를 지정할 수 있습니다. (예> "%[^a-zA-Z]%" 두 % 사이에 영문자가 없는 패턴)
"^.[$()|*+?{"같은 특수 문자는 백슬레쉬('')를 사용해서 escape될 수 있습니다( 역자 주 : escape 이란 다른 말로 literal로 탈출한다라고 할 수 있습니다 즉 특수문자로 인식되지 않고 일반 문자로 인식되게 합니다). 사용하는 관점에서 보면 백슬레쉬도 PHP3의 문자열에서 escape되어야 하기 때문에 예를 들어 "($|?[0-9]+"같은 정규표현식은 ereg("(\$|?[0-9]+", $str) 와 같이 사용됩니다 (이 표현식은 무얼 검사하는 걸까요? ^^;(이건 역자가 한 말이 아닙니다))
하지만 []안에서는 특수문자가 모두 효력을 읽게 되기 때문에 이 법칙을 벗어남을 기억하세요 []안에서는 백슬레쉬를 포함한 모든 특수문자들이 그 힘을 읽습니다 (예> "[*+?{}.]"는 말그대로 '*', '', '+', '?', '{', '}', '.' 문자를 의미합니다. 그리고 regex man 페이지에 나오듯이 ']'문자 자체를 포함하려면 문자들 리스트의 첫 번째에 위치시킵니다('^'가 있으면 '^'뒤에). '-'를 포함하려면 첫 번째 또는 마지막 문자로 지정하고 '-'문자가 영역의 경계 (예> a에서 -까지)일 경우 영역지정 문자의 두 번째 경계로 지정([a--])합니다.
완벽한 설명을 하려면 대조 순서(collating sequences), 문자 클래스(character classes), 동일 클래스(equivalence classes)에 대해서도 다루어야 하지만 이 글에서는 별 상관관계가 없기 때문에 regex man 페이지를 참고하도록 합니다.
활용
(ja+)[a-zA-Z]* : ja로 시작하는 모든 문장을 찾습니다.
more..
-Validating Money Strings (금액 문자열 검사하기)
ok 이제 우리는 여기서 배운 것을 뭔가 실질적인 것에 적용 시켜봅시다. 사용자가 입력한 금액을 검사하는 정규표현식에 대해 알아봅니다. 금액은 "10000.00" 와 "10,000.00", 와, 센트 없이, "10000" 와 "10,000" 이렇게 4가지 방법으로 사용됩니다. (역자주 : 달러와 센트 군요 蝁,.蝁)
다음 정규표현식을 기초로 시작해 봅시다.
^[1-9][0-9]*$
이 정규표현식은 0으로 시작하지 않는 어떠한 수인지를 검사합니다. 하지만 "0"도 통과되지 못합니다. 그래서 다음과 같이 수정합니다.
^(0|[1-9][0-9]*)$
말로 표현하면 "0 이거나 0으로 시작하지 않는 수"입니다. 이제 수 앞에 -부호도 사용할 수 있게 수정해 봅니다.
^(0|-?[1-9][0-9]*)$
이 뜻은 "0 이거나 -이 있을 수 있는 수이고 이 수는 0으로 시작하지 않는다"입니다. 이제 좀 느슨하게 하고 유저가 0으로 시작하는 수도 입력할 수 있도록 해봅니다. 금액에 필요없는 -부호도 없애버립니다. 그리고 선택사항인 소수점 부분 패턴도 넣어서 다음 정규표현식이 나옵니다.
^[0-9]+(.[0-9]+)?$
하이라이트된 부분은 소수점(.)이 항상 최소한 하나이상의 수와 붙어 있어야 함을 의미합니다. 그러므로 예를 들면 "10."은 통과되지 못하고 "10" 과 "10.2"는 통과합니다.
^[0-9]+(.[0-9]{2})?$
이제 소수점 뒤에 반드시 2개의 수가 붙어 있어야 합니다. 이게 너무 심하다 싶으면 다음과 같이 해서
^[0-9]+(.[0-9]{1,2})?$
소수점 뒤에 하나의 숫자만 올 수도 있게 합니다. 이제 1000단위를 구분하는 ','를 표현해 봅니다.
^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
"1~3개의 숫자와 그 뒤에 ','와 3개의 숫자로 이루어진 부분이 0개 또는 그 이상이 붙어 있는 패턴". 쉽죠? 이제 ','도 선택사항(옵션:option)으로 만들어 봅니다.
^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
이게 전부입니다. 여기서 '+'를 '*'로 바꾸면 빈 문자열도 통과되는 패턴이 됩니다. 함수호출할 때 백슬래쉬 문자 escape하는 것 (역자 : /를 //로) 잊지 마세요. 일단 문자열이 검사되어 지면 str_replace("," , "" , $money) 함수로 ','를 없애버리고 double로 형 변환을 해서 산술연산에도 사용할 수 있게 합니다.
- Validating E-mail Addresses (E-mail 주소 검사하기)
이제 e-mail 주소를 살펴봅시다. e-mail주소는 3부분으로 구성됩니다. : user 명(@왼쪽편에 있는 모든 것), '@', 그리고 서버명(나머지 부분들) user명은 대문자 또는 소문자와 숫자, '.' '-', '_'로 구성됩니다. '_'를 제외하면 서버명도 마찬가지입니다. user 명은 .으로 시작하거나 끝나지 않습니다. domain명도 마찬가지입니다. 또한 .이 연속으로 있을 수도 없고 . 사이에는 최소한 하나 이상의 문자가 있어야 합니다. 이제 user명 부분을 검사하는 정규표현식을 만들어 봅시다.
^[_a-zA-Z0-9-]+$
이 정규표현식은 아직 .을 지원하지 않습니다. 다음과 같이 수정합니다.
^[_a-zA-Z0-9-]+(.[_a-zA-Z0-9-]+)*$
말로 하면 "최소한 하나의 유효한 문자(valid character)와 그 뒤에 .과 유효문자들로 구성된 부분이 0또는 그 이상이 있는 패턴"입니다.
좀 간단하게 하기 위해 이 정규표현식을 ereg()대신에 eregi()함수에 사용합니다. eregi()함수는 대소문자를 구분하지 않기 때문에 "a-z"와 "A-Z"같이 두 개의 영역을 지정하지 않아도 되는 이점이 있습니다.(둘 중 어떤 것이라도 상관없음)
^[_a-z0-9-]+(.[_a-z0-9-]+)*$
서버명의 경우 '_'만 제외하고는 동일합니다.
^[a-z0-9-]+(.[a-z0-9-]+)*$
이제 '@'를 중심으로 서로 붙여서 다음과 같이 만들어 냅니다.
^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*$
* 정규식에 관한 것들
jakarta project 의 Regexp 패키지에 관한글 http://www.superuser.co.kr/jsp/jsp02/page24.htm
php에서의 정규식 http://blog.naver.com/hbini?Redirect=Log&logNo=80029262521
java의 공식적 정규식 문서 http://java.sun.com/developer/technicalArticles/releases/1.4regex/
2006년 10월 9일 월요일
find 명령어 사용하기
유닉스에서 find 기능 이용하기 | |||||||||||||||||||||||||||||||||||
등록: 한빛미디어(주) | |||||||||||||||||||||||||||||||||||
저자: 드루 라빈, 역 이호재 find where_to_search expressions expression 부분은 처음 find를 사용할 때 상당히 혼란스러운 부분입니다. 또한 이 부분은 유닉스마다 조금씩 다른 문법을 가지고 있습니다. 그래서 새로운 시스템에서 find를 이용하고자 한다면 find의 맨페이지를 살펴봐야 합니다. FreeBSD에서 많이 사용되는 expression은 다음과 같습니다.
whatis find find(1) - walk a file hierarchy 대략적으로 보자면, find는 당신이 선택한 어떤 표현식에 맞는 파일들을 찾기 위해 디렉토리를 재귀적으로 검색하는 것을 의미합니다. 이러한 기능이 별것 아닌 것처럼 보일수 있지만, 디렉토리와 그 모든 서브 디렉토리를 검색할 수 있는 유닉스 유틸리티는 많지 않습니다. 이러한 유용한 기능은 파일을 찾는 것뿐만이 아니라 다른 일도 할 수 있습니다. find . -print "."는 당신의 현재 디렉토리를 의미하기 때문에, 이 find 명령어는 현재 이 명령어가 실행되고 있는 디렉토리와 그 모든 서브 디렉토리에 있는 파일을 찾아서 화면에 출력할 것입니다. find . 하지만 -print 옵션을 default로 하지 않는 시스템도 있기 때문에 -print 옵션을 쓰는 습관을 들이는게 좋습니다. cd find . -print cd 명령어는 당신을 home 디렉토리로 이동시켜 줍니다. find 명령어를 통해서 매우 강력한 일을 할 수 있기 때문에, find 명령을 실행시킬 디렉토리로 우선 이동한 후 작업을 시작하는 것이 좋은 습관입니다. 지금부터 필자는 당신이 home 디렉토리에 있다고 가정할 것이고, 이는 부주의로 인해 home 디렉토리 이외의 다른 파일에 나쁜 영향을 끼치는 것을 방지할 것입니다. touch file1 find . -name file1 -print ./file1 위의 명령어를 하나하나 살펴보도록 하겠습니다. 먼저 touch 명령어를 이용해서 이름이 file1인 빈 파일을 하나 생성하였습니다. 그리고나서 find 명령을 내릴때 현재 디렉토리(".")에서부터 찾을 것이며 파일이름(-name)이 file1인 것을 찾고 그결과를 화면에 출력하라는 옵션을 주었습니다. 위의 결과에서 file1이 하나 출력되었기 때문에 필자는 현재 디렉토리와 그 하위 디렉토리에 파일이름이 file1인 것은 단 하나 존재한다고 말할 수 있습니다. find . -name "*.pdf" -print ./pdfs/50130201a.pdf ./pdfs/50130201b.pdf ./pdfs/50130201c.pdf ./pdfs/IWARLab.pdf ./pdfs/DoS_trends.pdf ./pdfs/Firewall-Guide.pdf ./2000_ports.pdf 최근에는 필자가 비교적 정리를 잘 한 것 같습니다. pdfs이외의 디렉토리에 있는 pdf파일이 하나밖에 없으니까요. find . -name \*.pdf -print find . -name '*.pdf' -print 이의 명령어에 명령어를 추가해보고 결과가 어떻게 바뀌는지 살펴보도록 합시다. 만약 pdfs 디렉토리 내에 있지 않은 pdf 파일만을 찾고자 한다면 어떻게 해야 할까요? 위의 명령어의 결과를 pipe를 통해 grep에게 전달하면 됩니다. find . -name "*.pdf" -print | grep -v "^\./pdfs/" ./2000_ports.pdf 음...위의 명령어는 동작을 합니다만 문법이 꽤 이상해 보입니다. 이를 분석해 보도록 하겠습니다. grep에서 -v는 역필터를 설정하는 옵션입니다. 즉 grep -v 다음에 나오는 것과 반대되는 것을 보여주는 것입니다. 이번 예에서 ./pdfs/에 들어있는 파일들은 필요 없기 때문에 ./pdfs/에 들어 있지 "않은" 파일을 찾아야 했고 그래서 -v 옵션을 사용했습니다. 또 전체 표현식을 인용부호로 감싼 것을 볼 수 있습니다. 그리고 추가적인 문자인 ^\ 를 볼 수 있습니다. ^는 grep에게 표현식이 각 라인의 1열에서부터 일치한 것만을 찾으라고 말하는 것입니다. \는 .를 특별한 문자로 해석하지 못하게 하기 위해 쓰인 추가적인 인용부호입니다. 표현식 전체는 grep에게 ./pdfs/ 디렉토리에 있지 않는 파일들을 보여달라는 것을 의미합니다. 그래서 원하는 결과를 얻었습니다. find . -name "*.pdf" -print | grep -v "^\./pdfs/" | xargs -J X mv X ./pdfs/ 이 명령어가 정확하게 작동했는 지를 알아보기 위해 원래의 find 명령어를 반복하겠습니다. find . -name "*.pdf" -print ./pdfs/50130201a.pdf ./pdfs/50130201b.pdf ./pdfs/50130201c.pdf ./pdfs/IWARLab.pdf ./pdfs/DoS_trends.pdf ./pdfs/Firewall-Guide.pdf ./pdfs/2000_ports.pdf 위에서 볼 수 있듯이 정확하게 동작하였습니다. 왜 그런지 살펴보도록 하겠습니다. 일단 grep은 find 의 결과를 필터링 하였습니다. 그 grep의 결과값이 pipe를 통해 xargs 명령어로 전달이 되었고 우리가 원하는 일이 완료되었습니다. J 스위치는 xargs 명령어에게 stdin으로 들어오는 모든 파일들을 소스로, 명령어 다음에 나오는 파일을 목적지로 가정하게 합니다. 예를 들면 필자가 find 명령을 내리기 전에는 얼마나 많은 파일들을 옮겨야 하는지 알 수 없었습니다. 하나일수도 있고 여러개일수도 있기 때문입니다. 필자는 찾은 파일이 몇개인지 상관없이 xargs가 해당 파일 모두를 pdfs 디렉토리로 옮기게 하고 싶었습니다. 이러한 일종의 마법같은 작업이 J 스위치로 인해 가능합니다. 또한 J 스위치가 올바르게 작동하기 위해서 X라는 문자열을 정의하였고 mv 다음에 삽입하였습니다. 유닉스 파일은 확장자가 없을 수 있다는 것을 기억해야 합니다. 그래서 좀 더 복잡한 패턴에 일치하는 파일을 찾을 수 있어야 합니다. 예를 들면 파일 이름안에 "bsd"가 들어 있는 것을 찾고 싶다면 다음과 같은 명령어를 내리면 됩니다. find . -name "*bsd*" -print ./.kde/share/icons/favicons/www.freebsd.org.png ./.kde/share/icons/favicons/www.freebsddiary.org.png ./.kde/share/wallpapers/bsdbg1280x1024.jpg ./mnwclient-1.11/contrib/freebsd 우리는 물론 파일이름뿐만 아니라 다른 것으로도 파일을 찾을 수 있습니다. 예를 들면, 여러분이 읽은지 30일 이상이 지난 파일들을 찾고자 한다면 다음과 같이 하면 됩니다. find . -atime +30 -print 수정하지 않은 파일을 찾고자 한다면 -mtime을 사용하면 됩니다. 그리고, 소유권을 변경하지 않은 파일을 찾고자 한다면 -ctime을 사용하면 됩니다. + 다음의 숫자는 날짜를 의미합니다. 오늘 변경된 파일을 찾고자 한다면 다음과 같이 하면 될 것입니다. find . -mtime -1 -print 이는 24시간내에 수정된 파일을 찾아서 보여줍니다. 이번 예제에서는 하루 이전의 파일에 관심이 있기 때문에 - 옵션을 사용한 것에 주목하시기 바랍니다. find . -type f -name ".*" -newer .cshrc -print 여기에 -type이란 새로운 스위치가 있습니다. 이는 파일의 타입을 지정하는 스위치인데 디렉토리가 아닌 파일만을 찾기 위해 -type f를 추가했습니다. 그리고 -name 스위치를 통해 이름이 .으로 시작하는 파일을 찾고자 했으며 마지막으로 -newer 스위치를 이용해 .cshrc 파일을 수정한 이후에 수정된 파일들을 찾도록 하였습니다. find . -atime +7 -size +20480 -print 하지만 만약 7일 이상 접근하지 않은 파일 이거나 크기가 10MB이상인 파일을 찾고자 한다면 다음처럼 해야 합니다. find . -atime +7 -o -size +20480 -print 여기서 -size 스위치를 사용하기 위해서 약간의 계산이 필요하다는 것을 알 수 있습니다. 이는 -size가 크기를 512바이트 단위로 인식하기 때문입니다. 하지만 다음과 같이 한다면 계산은 필요없습니다. find . -atime +7 -o -size +`expr 10 \* 1024 \* 2` -print 위의 예제에서 backquotes(`) 사이에서 우리가 필요로하는 계산을 한다는 것을 주목해야 합니다. (`는 키보드의 가장 왼쪽 상단에 있습니다.) 우리는 10MB 이상의 파일을 찾길 원하기 때문에 backquotes 앞에 +가 여전히 존재합니다. find 명령어 앞에 echo를 더해서 그 결과가 무엇인지 미리 알아볼 수도 있습니다. echo find . -atime +7 -o -size +`expr 10 \* 1024 \* 2` -print find . -atime +7 -size +20480 -print 위와 같이 복잡한 명령어를 실행할 때에는, backquote를 한 것이 올바른 결과를 출력하는지 등을 미리 검사해 보는 것이 좋은 습관입니다. | |||||||||||||||||||||||||||||||||||