고용량의 텍스트 파일(25기가가 넘는 로그파일)을 보려니 일전에 올렸던 LTF 역시 답답해서 파일 분할, 검색 하기로 했다.
사실 결국 컴퓨터 사양이 좋으면, 로그를 꼭 필요한 것만 출력해서 용량차지가 적도록, 혹은 애초에 로그를 분석할 필요가 없는 코드를 짰다면 이런 일이 발생하지 않는데 아무튼 상황을 이지경으로 만든 사람은 누군지도 이 자리에 있지도 않으니 이런 잡 기술만 늘어가는 중이다.
virtual 키워드를 사용하여 가상 디렉토리로 시작하는 경로를 나타냄. "header.inc"라는 파일이 /html 이라는 가상 디렉토리에 있는 경우 다음 줄은 "header.inc"의 내용을 삽입함. <!-- #include virtual = "/html/header.inc" -->
file 키워드
file 키워드를 사용하면 상대경로를 나타냄. 산대경로는 포함 파일이 포함된 디렉토리로 시작함. html 디렉토리에 파일이 있고, "header.inc"파일이 html/headers에 있는 경우 다음 줄은 파일에 "header.inc"를 삽입함. <!-- #include file = "headers/header.inc" -->
포함된 파일의 경로 (header/header.inc)는 포함된 파일에 상대적임. 이 #include 문이 포함된 파일이 html 디렉토리에 없으면 명령문은 작동하지 않음.
기타 참고사항
위 섹션에서는 포함된 파일에 대해서 확장자 .inc를 사용했음. 사용자가 inc 파일을 직접 탐색하려고 하면 해당 내용이 표시됨. 포함된 파일에 기밀 정보나 다른 사용자에게 보여주고 싶지 않은 정보가 포함되어 있다면, ASP 확장자를 사용하는 것이 좋음. ASP 파일의 소스 코드는 해석 후에 보이지 않음. 포함된 파일에는 다른 파일명도 포함될 수 있으며 하나의 ASP 파일에는 동일한 파일이 두번 이상 포함될 수 있음.
중요 : 포함된 파일은 스크립트가 실행되기 전에 처리되고 삽입됨. 다음 스크립틍는 ASP가 변수 값을 할당하기 전에 #include 지시문을 실행하기 때문에 작동하지 않음.
find는 리눅스에서 파일 또는 디렉토리를 계층구족로 검색할 때 사용함. 원하는 파일을 찾는데 오래 걸리긴 하지만 생각보다 활용도나 활용 빈도가 높아서 정리해 보기로 함.
명령어 구조
일반적인 리눅스 명령어와는 다르게 find 명령은 옵션보다 표현식이 더 많이 사용 됨. 검색 결과가 지정된 표현식의 조합에 따라 많이 달라짐. (참조한 문서들에서 연산자 혹은 표현식, 명령어 등 표현이 다양해서 설명하다 용어가 바뀔 수 있음 주의.)
find --help
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
기본 경로로는 현재 디렉토리; 기본 표현식은 -print.
표현식은 연산자, 옵션, 테스트 및 조치로 구성됨:
연산자 (우선순위 감소; -다른 항목이 지정되지 않은 경우 암시적) :
( EXPR ) ! EXPR -not EXPR EXPR1 -a EXPR2 EXPR1 -and EXPR2
EXPR1 -o EXPR2 EXPR1 -or EXPR2 EXPR1 , EXPR2
위치 옵션 : -daystart -follow -regextype
일반 옵션 (always true, 다른 표현식 앞에 지정됨):
-depth --help -maxdepth LEVELS -mindepth LEVELS -mount -noleaf
--version -xdev -ignore_readdir_race -noignore_readdir_race
테스트 (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N
-cnewer FILE -ctime N -empty -false -fstype TYPE -gid N -group NAME
-ilname PATTERN -iname PATTERN -inum N -iwholename PATTERN -iregex PATTERN
-links N -lname PATTERN -mmin N -mtime N -name PATTERN -newer FILE
-nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN
-readable -writable -executable
-wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N
-used N -user NAME -xtype [bcdpfls]
-context CONTEXT
실행 옵션 : -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print
-fprint0 FILE -fprint FILE -ls -fls FILE -prune -quit
-exec COMMAND ; -exec COMMAND {} + -ok COMMAND ;
-execdir COMMAND ; -execdir COMMAND {} + -okdir COMMAND ;
옵션
DESC
-P
심볼릭 링크를 따라가지 않고, 심볼릭 링크 자체 정보 사용.
-L
심볼릭 링크에 연결된 파일 정보 사용.
-H
심볼릭 링크를 따라가지 않으나, Command Line Argument를 처리할 땐 예외.
-D
디버그 메세지 출력
표현식
DESC
-name
지정된 문자열 패턴에 해당하는 파일 검색.
-empty
빈 디렉토리 또는 크기가 0인 파일 검색.
-delete
검색된 파일 또는 디렉토리 삭제.
-exec
검색된 파일에 대해 지정된 명령 실행.
-path
지정된 문자열 패턴에 해당하는 경로에서 검색.
-print
검색 결과를 출력. 검색 항목은 newline으로 구분(기본값).
-print0
검색 결과를 출력. 검색 항목은 null로 구분.
-size
파일 크기를 사용하여 파일 탐색.
-type
지정된 파일 타입에 해당하는 파일 검색.
-mindepth
검색할 하위 디렉토리 최소 깊이 지정.
-maxdepth
검색할 하위 디렉토리 최대 깊이 지정.
-atime
파일 접근(access) 시각을 기준으로 파일 검색.
-ctime
파일 내용 및 속성 변경(change) 시각을 기준으로 검색.
-mtime
파일의 데이터 수정(modify) 시각을 기준으로 검색.
표현식 사용시 연산자를 이용하면 두 개 이상의 표현식 조합이 사용가능. find 명령에서 두 개 이상의 표현식을 사용할 경우 연산자를 지정하지 않으면 기본적으로 AND 연산자가 적용됨.
표현식
DESC
(expression)
expression 우선순위 지정.
!expression
-not expression
expression 결과에 NOT 연산
expression -a expression
expression -and expression
expression expression
expression 간 AND 연산
expression -o expression
expression -or expression
expression 간 OR 연산
find 명령 사용 예제
현재 디렉토리 내에서 지정된 이름의 파일을 찾는 것은 간단함. find 명령 뒤에 파일 이름을 지정하면 됨.
[root@ASDF ~]# ls
WAS-2.csv anaconda-ks.cfg install.log install.log.syslog watch.sh 공개 다운로드 문서 바탕화면 비디오 사진 음악 템플릿
[root@ASDF ~]# find watch.sh
watch.sh
보통 현재 디렉토리에서 파일을 찾을 땐 ls | grep 이거로 찾기 때문에 현재 디렉토리와 하위 디렉토리에 위치한 파일을 찾을 경우에는 find . -name "이거"를 사용함.
요약 예제
예
설명
find
현재 디렉토리에 있는 파일 또는 디렉토리 리스트 표시.
find [PATH]
대상 디렉토리에 있는 파일 또는 디렉토리 표시.
find . -name [FILE]
현재 디렉토리 및 하위 디렉토리에서 파일 또는 디렉토리 검색.
find / -name [FILE]
전체 파일 시스템에서 파일 검색.
find . -name "STR*"
이름이 특정 문자열로 시작하는 파일 검색.
find . -name "*STR"
이름이 특정 문자열로 끝나는 파일 검색.
find . -name "STR"
이름에 특정 문자열이 포함된 파일 검색.
find . -empty
크기가 0인 파일 또는 디렉토리 검색.
find . -name "*.EXT" -delete
특정 확장자를 가진 모든 파일 검색 후 삭제.
find . -name [FILE] -print0
검색된 리스트를 줄 바꿈 없이 이어서 출력
find . -name [FILE] -type f
파일 또는 디렉토리만 검색하기
find . -size +[N]c -and -size -[M]c
파일의 크기를 사용하여 파일 검색.
find . -name [FILE] -exec ls -l {} ;
검색됱 파일에 대한 상세 정보 출력.
find . -name [FILE] -exec grep "STR" {} ;
검색된 파일에서 문자열 찾기
find . -name [FILE] > [SAVE_FILE]
검색 결과를 파일로 저장.
find . -name [FILE] 2> /dev/null
검색 중 에러 출력하지 않기.
find . -maxdepth 1 -name [FILE]
하위 디렉토리 검색하지 않기.
find . -name [FILE] -exec cp {} [PATH] ;
검색된 파일 복사.
예제
현재 디렉토리에 있는 파일 및 디렉토리 리스트 표시
옵션 없이 find 명령만 사용하면 현재 디렉토리에 있는 모든 파일과 디렉토리(하위 디렉토리를 포함) 표시. 주로 디렉토리의 파일 리스트를 다른 명령으로 전달, 처리할 때 사용함.
# 현재 디렉토리의 파일 및 디렉토리 출력.
find
# 현재 디렉토리의 모든 내용을 줄 바꿈 없이 출력.
find -print0
대상 디렉토리에 있는 파일 및 디렉토리 리스트 표시
대상 디렉토리에 있응 파일 및 디렉토리 리스트 표시.
find [PATH]
현재 디렉토리 아래 모든 파일 및 하위 디렉토리에서 파일 검색
현재 디렉토리에 포함 된 모든 하위 디렉토리 및 파일에서 지정된 파일을 검색.
find . -name [NAME]
전체 파일 경로에서 검색
디렉토리 경로를 루트(/)로 지정하여 전체 경로에서 검색.
find / -name "NAME"
파일 이름이 특정 문자열로 시작하는 파일 검색
특정 문자열로 시작하는 파일 검색.
find . -name "STR*"
파일 이름에 특정 문자열을 포함하는 파일 검색
find . -name "*STR*"
파일 이름이 특정 문자열로 끝나는 파일 검색
find . -name "*STR"
빈 디렉토리 또는 크기가 0인 파일 검색
-empty 옵션을 넣으면 빈 디렉토리 또는 크기가 0인 파일 검색 가능.
# 빈 디렉토리 또는 크기가 0인 파일 검색.
find . -empty
# STR 이라는 이름의 빈 디렉토리 또는 크기가 0인 파일 검색.
find . -name STR -empty
특정 파일을 검색 후 삭제
-delete 옵션을 사용하면 검색된 파일 및 디렉토리를 삭제함. 검색 결과의 디렉토리가 비어있지 않으면 삭제되지 않음.
find . -empty -delete
검색된 결과를 줄 바꿈 없이 이어서 출력
find의 기본 옵션이 -print인데, -print0 옵션을 주게 되면 줄 바꿈 없이 출력 가능.
# 검색 결과를 줄 바꿈으로 구분하여 출력
find .
find . -print
# 검색 결과를 줄 바꿈 없이 출력.
find . -print0
파일 또는 디렉토리만 검색하기
-type 옵션을 사용하여, 파일의 종류를 지정할 수 있음.
d : directory special
f : regular file
l : symbolick link
# 이름에 A가 포함되는 일반 파일 검색
find . -name "*A*" -type f
# 이름에 A가 포함되는 디렉토리 검색
find . -name "*A*" -type d
파일의 크기를 이용하여 검색
-size 옵션을 사용하면 파일의 크기로 찾을 수 있음. 기본적으로 block 단위르 사용함. 파일 크기 뒤에 b, c, w, k, M, G 를 붙임으로 단위를 바꿔 조회 가능.
b : block
c : bytes
w : 2bytes
k : kb
M : MB
G : GB
크기 앞에 +(초과), -(미만)으로 범위 조건을 부여 가능하며, -size 옵션을 조합하여 크기의 범위를 사용 가능.
# 파일 크기가 1024 bytes인 파일 검색.
find . -size 1024c
# 파일 크기가 1024 bytes를 초과하는 파일 검색.
find . -size +1024c
# 미만인 파일 검색.
find . -size -1024c
# 1024 초과, 2048 미만
find . -size +1024c -size -2048c
검색된 파일에 대한 상세 정보 출력
-exec 옵션으로 검색된 결과를 이용해 다른 명령 실행 가능.
ls
BbsAuthorBindingInterceptor.class LoginAuthorBindingInterceptor.class ProgrmAuthorBindingInterceptor.class TemplateBindingInterceptor.class TemplateMainBindingInterceptor.class-bk_20210209
ControllerInterceptor.class NeoAuthorBindingInterceptor.class ProgrmAuthorBindingInterceptor.class-20210320 TemplateBindingInterceptor.class-bk_20210203
ControllerInterceptorAdapter.class NeoAuthorBindingInterceptor.class-bk_20210407 StaffAuthorInterceptor.class TemplateMainBindingInterceptor.class
# 현재 디렉토리에서 *.class 파일들의 상세정보 출력
find . -name "*.class" -exec ls -al {} \;
-rw-rw-r-- 1 user user 6475 2021-03-20 16:17 ./ProgrmAuthorBindingInterceptor.class
-rw-r--r-- 1 user user 2273 2019-12-07 22:58 ./StaffAuthorInterceptor.class
-rw-rw-r-- 1 user user 5819 2016-03-17 18:00 ./BbsAuthorBindingInterceptor.class
-rw-rw-r-- 1 user user 1323 2015-08-24 16:54 ./ControllerInterceptor.class
-rw-r--r-- 1 user user 4948 2021-01-15 12:33 ./LoginAuthorBindingInterceptor.class
-rw-rw-r-- 1 user user 8673 2021-04-07 09:41 ./NeoAuthorBindingInterceptor.class
-rw-r--r-- 1 user user 5455 2019-12-08 14:22 ./ControllerInterceptorAdapter.class
-rw-rw-r-- 1 user user 3728 2021-02-09 15:56 ./TemplateMainBindingInterceptor.class
-rw-r--r-- 1 root root 13309 2021-02-09 15:56 ./TemplateBindingInterceptor.class
검색된 파일의 라인 수 출력
find 명령과 wc 명령을 조합하여 검색된 파일의 문자 수 또는 라인수를 계산하여 출력 가능.
#include <stdio.h>
#include <stdlib.h>
void main()
{
// 파일 포인터 선언
FILE *fp;
char c;
// 파일 생성이므로 텍스트 쓰기모드로 오픈.
fp = fopen("putc.tt.txt", "w");
// 파일 개방 여부 체크. -> 에러메세지와 프로그램 종료.
if (fp == NULL)
{
printf("FAIL TO OPEN FILE");
exit(1);
}
// 문자 출력의 끝 확인.
while ((c = getchar()) != EOF)
{
// 문자를 파일로 출력.
putc(c, fp);
}
printf("END OF WHILE!");
fclose(fp);
}
fputs()
문자열을 파일로 출력.
형식 : fputs(문자열변수, 파일포인터변수);
사용 예 : fputs(s, fp);
기능 : 지정된 파일에 문자열(하나의 레코드) 출력.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main() {
char name[64];
FILE *fp;
// 텍스트 쓰기모드 개방하고, 에러시 프로그램 종료.
if ((fp = fopen("02_fputs.tt.txt", "w")) == NULL) {
puts("CAN NOT OPEN FILE");
exit(1);
}
gets(name);
while (strcmp(name, "end")) {
// 하나의 문자열에 개행문자 추가.
strcat(name, "\n");
// 문자열을 fp가 가르키는 파일에 수록.
fputs(name, fp);
gets(name);
}
printf("BYE!\n");
// 파일 닫기.
fclose(fp);
}
fprintf()
지정된 형식을 가지로 파일에 자료를 출력.
여러 항목의 복합적인 자료로 구성된 레코드를 저장할 때 유용.
형식 : fprintf(파일포인터변수, "출력형식", 변수);
사용 예 : fprintf(fp, "%s %d\n", a, b);
기능 : 지정된 형식대로 자료를 파일포인터 변수가 가리키는 곳에 출력.
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp;
char no[10], name[10];
int mid, term, rep, att, i;
if ((fp = fopen("03_fprintf.tt.txt", "w")) == NULL)
{
puts("CAN NOT OPEN FILE");
exit(1);
}
// stdout : 모니터를 가리키는 특수한 파일포인터.
fprintf(stdout, "insert no name mid term rep att.");
for (i = 0; i < 5; ++i)
{
scanf("%s %s %d %d %d %d", no, name, &mid, &term, &rep, &att);
// 지정된 형식으로 자료를 파일에 출력.
fprintf(fp, "%10s %8s %3d %3d %3d %3d\n", no, name, mid, term, rep, att);
}
printf("BYE!\n");
// 파일 닫기.
fclose(fp);
}
C 언어에서 입출력 장치를 파일 개념으로 처리
자동적으로 3개의 표준 파일에 대한 포인터를 생성함.
이러한 표준 파일에 대해서는 다로 파일포인터를 선언할 필요가 없음.
표준파일
파일 포인터
대응 장치
입력
stdin
키보드
출력
stdout
모니터
에러
stderr
모니터
순차파일 입력함수
파일 출력함수에 의해 만들어진 순차파일의 저장된 자료를 읽어내는 함수. 자료를 읽을 때는 파일의 끝에 있는 EOF 신호를 만날 때까지 읽을 수 있는 프로그램 작성.
getc(), fgetc(), fgets(), fscanf()
getc()
문자 단위의 파일 입력함수.
fgetc() 함수와 유사.
형식 : getc(파일포인터변수);
사용예 : c = getc(fp);
기능 : 지정된 파일로부터 한 문자를 읽어온다.
#include <stdio.h>
#include <stdlib.h>
void main() {
FILE *fp;
char c;
if ((fp = fopen("01_putc.tt.txt", "r")) == NULL) {
puts("\n\nCAN NOT OPEN FILE");
exit(1);
}
while ((c = getc(fp)) != EOF) {
putchar(c);
}
printf("\n\nBYE!\n");
// 파일 닫기.
fclose(fp);
}
fgets()
파일에 저장된 문자열 자료를 읽을 때 사용.
읽어 낼 문자열의 길이를 반드시 명시.
형식 : fget(문자열변수, 문자열 길이 + 1, 파일포인터 편수);
사용 예 : fget(s, 40, fp);
기능 : 지정된 파일로부터 해당 문자열 길이 만큼의 문자를 읽어 문자열 변수에 저장한다.
#include <stdio.h>
#include <stdlib.h>
void main() {
char name[20];
FILE *fp;
if ((fp = fopen("02_fputs.tt.txt", "r")) == NULL) {
puts("\n\nCAN NOT OPEN FILE");
exit(1);
}
// 파일의 끝에 도달할 때까지 읽기.
while (fgets(name, 20, fp) != NULL) {
printf("%s", name);
}
printf("\n\nBYE!\n");
// 파일 닫기.
fclose(fp);
}
scanf()
숫자, 문자 등 복합적인 자료로 구성된 레코드를 읽을 때 사용.
일반적으로 파일의 끝을 판별하는 feof()와 같이 사용.
형식 : fscanf(파일포인터변수, "입력형식", 변수);
사용 예 : fscanf(sp, "%s %d", &a, &b);
기능 : 파일 포인터가 가리키는 곳으로부터 지정된 형식대로 자료를 읽어온다.
#include <stdio.h>
#include <stdlib.h>
void main() {
FILE *fp;
char no[10], name[10];
int mid, term, rep, att;
if ((fp = fopen("03_fprintf.tt.txt", "r")) == NULL) {
puts("\n\nCAN NOT OPEN FILE");
exit(1);
}
printf("no name mid, term, rep, att\n");
// 파일의 끝인지 확인하는 feof()
while (!feof(fp)) {
// 파일에 저장된 자료의 형식에 맞게 입력형식을 지정해야 함.
fscanf(fp, "%10s %8s %3d %3d %3d %3d\n", no, name, &mid, &term, &rep, &att);
printf("%-10s %-8s %4d %4d %4d %4d\n", no, name, mid, term, rep, att);
}
printf("\n\nBYE!\n");
// 파일 닫기.
fclose(fp);
}
레코드 추가를 위한 사용 모드
a a+ ab ab+
형식 : fp = fopen("파일명", "a");
사용 예 : fp = fopen("파일명", "a");
기능 : 이미 만들어진 순차파일의 끝에 새로운 레코드 추가(append).
#include <stdio.h>
void main() {
FILE *fp;
// 레코드 추가 모드로 파일 개방.
fp = fopen("04_tt.dat", "a");
// 파일이 없으르모 새 파일 생성 후 새 내용 기록.
fputs("asdf \n", fp);
fputs("qwer \n", fp);
fputs("zxcv \n", fp);
fputs("qaz \n", fp);
fputs("wsx \n", fp);
fclose(fp);
}
랜덤파일 처리 (random file)
파일의 임의의 위치에서 자료를 읽거나 쓸 수 있음.
레코드의 길이가 일정함.
순차파일에 비해
장점 : 레코드 탐색이 빠르고 효과적.
단점 : 기억공간 낭비.
랜덤파일 열기
일반적으로 랜덤파일을 입출력할 때는 2진 모드로 파일을 개방.
2진 모드의 특징
텍스트 파일보다 적은 기억공간.
레코드의 길이를 개발자가 결정.
파일 포인터의 위치 변경 가능.
랜덤파일 입출력 함수
fwrite()
레코드의 길이를 지정.
자료저장 변수는 포인터 형.
형식 : fwirte(저장자료변수, 레코드길이, 레코드개수, 파일포인터);
사용 예 : fwrite(name, 10, 1, fp);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
FILE *fp;
char name[10];
// 2진 파일 쓰기 모드 개방.
if ((fp = fopen("08_fwrite.dat", "wb")) == NULL)
{
puts("\n\nCAN NOT OPEN FILE");
exit(1);
}
gets(name);
while (strcmp(name, "END"))
{
// 2진 파일 쓰기.
fwrite(name, 10, 1, fp);
gets(name);
}
fclose(fp);
}
fread()
읽기에 성공하면 읽은 레코드 수를 리턴.
형식 : fread(읽을자료변수, 레코드길이, 레코드개수, 파일포인터);
ex : fread(name, 10, 2, fp);
#include <stdio.h>
#include <stdlib.h>
void main() {
FILE *fp;
char name[10];
// 2진 파일 읽기 모드 개방.
if ((fp = fopen("08_fwrite.dat", "rb")) == NULL) {
puts("\n\nCAN NOT OPEN FILE");
exit(1);
}
while (1) {
// 레코드의 개수가 1이 아닌 값이 리턴되면 파일은 끝난다.
if (fread(name, 10, 1, fp) != 1)
break;
puts(name);
}
fclose(fp);
}
프로그램과 입출력 장치(콘솔, 파일, 소켓등)와의 사잉에 이루어 지는 자료의 입력과 출력.
자료의 입출력을 위한 논리넉인 통로 : 스트림
스트림 (stream)
stream
표준 입출력장치를 이용한 자료 입출력.
표준 입출력장치와의 스트림은 프로그램 실행/종료 시 자동으로 생성/소멸 됨.
파일 입출력을 위한 스트림은 프로그램을 통해 생성/소멸 시켜주어야 함.
파일 입출력의 수행 과정
과정
파일을 연다.
파일과 자료를 주고 받을 수 있는 스트림을 생성(fopen() 사용).
입출력을 수행한다.
파일을 닫는다.
생성된 스트림을 소멸시키기 위한 과정(fclose() 사용).
스트림(stream)의 생성
파일과 프로그램과의 통로(논리적인 접속)를 구성.
통로 역할을 파일포인터가 수행.
파일입출력 프로그램 구조
// 파일을 가리키는 파일포인터 선언.
FILE *fp;
// 파일 열기 : 지정한 모드로 열고, fp로 하여금 파일을 가리키게 함.
fp = fopen("파일명", "모드");
// 입출력 수행 : 파일처리함수와 fp를 이용하여 입출력 수행.
...
// 파일 닫기 : 버퍼를 비우고 fp가 가리키는 파일을 닫음.
fclose(fp);