Skip to content

find로 원하는 파일을 찾아보자! (1)

이번에는 파일을 찾을 때 사용하는 명령어인 find에 대해서 알아보려고 합니다.
우리는 보통 터미널에서 파일을 찾을 때 lsgrep을 활용해서 원하는 파일을 검색하곤 합니다.
파일의 이름과 경로를 어느정도 알고있다면 위 방법만으로도 충분히 원하는 결과를 얻을 수 있을겁니다.
그런데 권한, 변경 시간 같은 파일의 특징을 조건으로 파일을 찾아야 하는 경우에는 어떨까요?
현재 시각으로 부터 1시간 이내 변경이력이 있는 파일들을 검색하려면 기존에 알던 방법으로는 조금 어려워 보입니다.
find라는 명령어는 이런 경우 정말 유용하게 사용할 수 있습니다.
find는 옵션과 표현식을 통해 찾고자하는 파일의 상세 조건을 정의해서 검색할 수 있도록 도와줍니다.
파일명 뿐만 아니라 접근 및 변경시간, 권한 등의 속성을 기준으로 검색할 수 있어 아주 강력한 기능이죠.
한가지 추가로 알아둘 점은 지난 시간에 알아본 grep명령어와 마찬가지로 find또한 GNU버전과 FreeBSD버전이 있습니다.
Linux에서는 기본적으로 GNU버전이 설치되어 있고, Mac OS에는 FreeBSD버전이 설치되어 있는데, 이 글에서는 Linux에서 사용하는 GNU버전으로 실습을 진행합니다.
버전별로 출력결과와 옵션이 조금 다른 부분이 있으므로 참고해주세요!
그럼 find의 기본 사용법부터 알아보겠습니다.

1. 기본 사용법

    1. find [대상 경로] [표현식]
    1. find [옵션] [대상 경로] [표현식]

find는 위처럼 옵션(생략가능), 대상 경로, 표현식의 순서로 입력합니다.
먼저 옵션심볼릭 링크, 디버깅, 레벨에 관련해서 세세한 설정을 할 때 사용합니다.
당장 심볼릭 링크, 디버깅, 레벨 등 생소한 단어가 등장해서 불편하실 수 있지만 find의 핵심 기능들을 이해하는 데는 큰 문제가 없으므로 걱정하지 않으셔도 됩니다!
이 부분에 대해서는 뒤에서 다뤄보도록 하겠습니다.
대상 경로는 find를 수행할 경로를 의미하며 기본값은 현재 위치입니다.
별도의 옵션을 설정하지 않으면 대상 경로의 하위 디렉토리를 전부 탐색합니다.
표현식은 파일을 찾는 방법에 해당합니다.
우리는 표현식을 정의해서 시간, 권한, 이름과 같은 속성들을 기준으로 원하는 파일을 검색할 수 있습니다.
이 얘기는 표현식을 잘 이해하고 있을수록 우리가 원하는 파일을 찾기 쉽다! 라는 의미와 같습니다.
그럼 표현식에 대해서 알아볼까요?

2. Find의 표현식

  • 테스트: 찾으려는 파일의 속성 정의
  • 연산자: 테스트와 테스트의 검색 우선순위 정의
  • 액션: 검색한 파일을 인수로 다른 명령어를 실행할 수 있게 함.
  • 위치옵션: 테스트의 검색조건 변경.

표현식의 종류로는 위에 소개한 4가지가 있습니다.
이 중에서 가장 먼저 살펴볼 부분은 find에서 가장 많이 사용되는 표현식인 테스트입니다.
테스트에서는 어떤 속성들을 정의해서 파일을 검색하는지 알아보겠습니다.

3. 테스트

  • 시간 관련 테스트(min, time)
  • 최신 파일 검색 관련 테스트(newer)
  • 파일 권한 관련 테스트(perm mode, readable, writable, executable)
  • 그룹 및 사용자 관련 테스트(uid, uname, gid, gname, nouser, nogroup)
  • 파일명 관련 테스트(iname)
  • 파일 경로 관련 테스트(ipath)
  • 파일 타입 관련 테스트(type)
  • 기타 테스트(empty, size)

테스트는 위와 같이 시간, 명칭, 경로, 타입등을 조건으로 검색할 수 있습니다.
다양한 테스트들이 존재하지만 이번 글에서 전부 다루기에는 분량이 너무 방대합니다.
그래서 이번 글에서는 몇가지 테스트를 실습해 보며 테스트는 어떻게 사용하는 것인지 활용방법에 대해서 간단히 알아보고자합니다.
그럼 실습에 필요한 파일을 스크립트로 생성해 보겠습니다.

$ touch ex_file
$ stat ex_file
File: `ex_file`
Size: 0             Blocks: 0          IO Block: 4096   일반 빈 파일
Device: 802h/2050d    Inode: 68146425    Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/  centos)   Gid: ( 1000/  centos)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2021-09-22 23:01:02.576327037 +0900
Modify: 2021-09-22 23:01:02.576327037 +0900
Change: 2021-09-22 23:01:02.576327037 +0900
Birth: -


위 스크립트는 touchex_file이라는 파일을 생성하고, stat으로 해당 파일의 상태를 조회하는 내용입니다.
touch의 기본으로 사용하면 대상 파일의 접근(Access), 변경(Change), 수정(Modify) 시간을 현재 시간으로 변경하며, 대상 파일이 존재하지 않는 경우 빈 파일을 생성합니다.
이번 상황에서는 대상 파일이 없었기 때문에 파일을 생성했습니다.
stat은 대상 파일의 상세정보를 보여주는데, 위 내용에서 알 수 있다시피 Access, Modify, Change 항목을 통해 파일의 변경이력을 확인할 수 있습니다.

3.1 시간 관련 테스트

  • amin / cmin / mmin n : 현재 시각을 기준으로 n분전에 액세스/변경/수정한 파일
  • atime / ctime / mtime n : 현재 시각을 기준으로 n * 24시간전에 액세스/변경/수정한 파일

파일은 접근(Access), 변경(Change), 수정(Modify) 작업이 발생하는 경우 해당 시각을 상태 값으로 기록하게 됩니다.
변경수정의 차이는 뭘까요?
단어의 뜻은 별 차이가 없어보이지만 파일시스템에서는 구분해서 사용합니다.
파일명이 변경된 경우 변경만이 일어나고 파일 내용이 변경된 경우 변경과 수정이 모두 일어납니다.
시간 관련 테스트는 이 값을 기준으로 검색을 하는 테스트이며 각 테스트의 앞글자는 어떤 상태를 기준으로 검색할 것인지를 의미합니다.
그럼 실습을 통해 파일의 상태값을 확인해보고 테스트를 정의해서 검색해보도록 하겠습니다.

$ ls
ex_file
$ touch ex_file
$ stat ex_file
File: `ex_file`
Size: 0             Blocks: 0          IO Block: 4096   일반 빈 파일
Device: 802h/2050d    Inode: 68146425    Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/  centos)   Gid: ( 1000/  centos)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2021-09-23 00:36:17.338927315 +0900
Modify: 2021-09-23 00:36:17.338927315 +0900
Change: 2021-09-23 00:36:17.338927315 +0900
Birth: -
$ date
2021. 09. 23. (목) 00:36:25 KST
$ find ./ -amin 5
$ find ./ -amin 1
./ex_file


스크립트는 amin 테스트를 사용해 접근시간을 조건으로 파일들을 검색하는 과정을 보여주고 있습니다.
먼저 amin이 조건에 맞게 동작하는지 확인하기 위해서 touch로 대상 파일의 변경이력을 갱신하고, date로 현재 시간을 조회했습니다.
그리고 -amin 5-amin 1을 각각 실행한 결과가 다른것을 확인할 수 있습니다.

3.2 최신 파일 검색 관련 테스트

  • anewer / cnewer / newer 대상파일 : 파일을 기준으로 최근에 접근/변경/수정된 파일을 찾는다.

앞서 알아본 테스트는 현재 시간을 기준으로 파일을 검색한 반면, anewer/cnewer/newer 테스트는 대상 파일을 기준으로 조건을 검사합니다.
그럼 실습을 통해 대상 파일을 기준으로 검색하는지 알아보겠습니다.

[대상파일 이후 시간]

$ touch ex_target
$ stat ex_file ex_target
File: `ex_file`
Size: 0             Blocks: 0          IO Block: 4096   일반 빈 파일
Device: 802h/2050d    Inode: 68146425    Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/  centos)   Gid: ( 1000/  centos)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2021-09-23 00:36:17.338927315 +0900
Modify: 2021-09-23 00:36:17.338927315 +0900
Change: 2021-09-23 00:36:17.338927315 +0900
Birth: -
File: `ex_target`
Size: 0             Blocks: 0          IO Block: 4096   일반 빈 파일
Device: 802h/2050d    Inode: 68156757    Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/  centos)   Gid: ( 1000/  centos)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2021-09-23 01:02:41.155049619 +0900
Modify: 2021-09-23 01:02:41.155049619 +0900
Change: 2021-09-23 01:02:41.155049619 +0900
Birth: -
$ find ./ -anewer ex_file
./
./ex_target


[대상파일 이전 시간]

$ touch -t 202109230030 ex_target #YYYYMMDDhhmm
$ stat ex_target
File: `ex_target`
Size: 0             Blocks: 0          IO Block: 4096   일반 빈 파일
Device: 802h/2050d    Inode: 68156757    Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/  centos)   Gid: ( 1000/  centos)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2021-09-23 00:30:00.000000000 +0900
Modify: 2021-09-23 00:30:00.000000000 +0900
Change: 2021-09-23 01:26:40.068191800 +0900
Birth: -
$ find ./ -anewer ex_file
./


스크립트의 내용을 설명하자면 추가로 ex_target이라는 파일을 생성한 다음 anewer를 사용해서 ex_file접근 시간을 기준으로 최근에 접근한 파일을 찾는 과정을 보여줍니다.
그리고 touch -tex_target의 접근 시간을 대상파일 이전으로 변경하면 검색되지 않는것을 확인할 수 있습니다.
참고로 touch -t는 사용방법은 아래와 같습니다.

# touch -t 변경할 날짜 파일명 #YYYYMMDDhhmm
$ touch -t 202109221330 example_file #YYYYMMDDhhmm


마무리

이번 글에서는 기본적인 find의 사용법과 find를 구성하는 개념들 중에서 테스트에 대해 간단히 소개하는 시간을 가졌습니다. 다음에는 테스트를 통해 얻은 결과를 활용하는 연산자, 액션 그리고 옵션에 대해서 알아보겠습니다.

참고

  • 처음 배우는 셸 스크립트 - 한빛미디어

작성자: 성승익

작성일: 2021-09-21