리눅스에서 파일을 찾는 방법

이 글은 리눅스 환경에서 파일을 찾는 방법을 정리한 글이다. 리눅스 핵심 레퍼런스를 참고하여 작성하였다.

기준 환경:

Ubuntu 20.04.1 LTS (WSL2 by Windows 10 x64)


파일을 찾는 명령의 종류

Command Description
find 파일, 디렉토리 검색 중 가장 많은 옵션을 제공한다. 상대적으로 느리다.
locate (mlocate) 파일, 디렉토리 Index를 만들고, 해당 Index 로 검색을 수행한다.
which 셸의 탐색 경로 내에서 명령어의 위치를 찾는다.
type Bash 셸 내장 프로그램으로 which와 같은 기능이지만 더 빠르다.
whereis 매개변수로 주어진 디렉토리 목록에 대해 탐색한다.

find

find의 경우 Man Page가 굉장히 어려워 35 Practical Examples of Linux Find Command를 참고했다. 해당 페이지 제목에서도 알 수 있듯, 한 명령어 설명에 35개의 예제가 들어간다는 것부터 범상치 않음을 짐작할 수 있다. find는 정말 그 기능이 너무나 많다. 정말 강력하다고 할 수 있으나 인덱싱이 지원되지 않아 탐색 대상이 늘어나면 꽤 느려져서 전체 디렉토리 대상으로 수행할 거라면 Interactive한 일회성 작업에 적절할 것 같다.

아래의 모든 옵션은 직접 테스트 후 작성하였다.


1. 공통 기능

Option Description Example Output
! 옵션 앞에 !를 붙이면 NOT 조건이 된다. find ! -name "*.txt" “*.txt”에 매칭되지 않는 파일, 디렉토리만 출력

2. 이름 기반 검색

Option Example Ouput
(x) find 하위 디렉토리 전부 재귀적으로 출력 (grep 하려면 전체 방문을 기다려야 함)
-name find -name input.txt 하위 디렉토리에서 input.txt를 찾아 출력
-name “패턴” find -name "*.txt" *.txt에 매칭되는 파일/디렉토리 검색 (*만 사용 가능한지 모르겠음)
(폴더 명시) find /bin (options...) /bin 아래에서 검색을 수행
-type `find -type (f d)`

3. 권한 기반 검색

권한 비트 앞에 0, 1, 2 등 한 바이트가 더 표현할 수 있는데 SGID, Sticky Bit 등의 내용에 대해 잘 이해하고 있지 못해서 생략했다. 추후 보강하겠다.

Options Example Output
-perm 권한 find -perm 777 권한이 777인 파일, 디렉토리를 출력
-perm /권한 find -perm /u=r (이 부분은 스펙과 출력이 달라서 추후 갱신할 예정입니다.) user 권한이 r인 파일(Read-only), 디렉토리를 출력 (대신 첫 글자만 해석함. rw 등 안 됨)

4. 출력에 대해 다른 명령어 수행

-exec 옵션이 있는데, -exec COMMAND {} \;와 같이 표시하는 형태이다. {} 가 각 라인이 들어갈 placeholder인 듯하다. 다만 이는 Pipelining으로도 충분히 가능해보여서 (-exec은 스트리밍을 지원하는건가?) 설명은 생략한다.


5. 소유자 기반 검색

Option Example Output
-user 소유자명 find -user root root 소유의 파일, 디렉토리 출력
-group 그룹명 find -group sb sb 소유의 파일, 디렉토리 출력 (sb는 제 유저명입니다)

참고로 그룹의 목록은 /etc/group 파일에 텍스트로 저장돼있다 :)


6. 시간 속성 기반 검색

Option Example Output
-mtime N find ~ -mtime 1 1일 내에 변경된 ~ 내의 파일 출력
-atime 접근 시각 기준
-mtime +N -mtime -M find ~ -mtime +50 -mtime -100 N일보다 더 지나고 N일 보다 덜 지난 날짜 사이에서 변경된 ~ 내의 파일 출력
-cmin/mmin N find -cmin/mmin 60 현재 디렉토리 아래에 변경된 지 60분 이내의 파일 출력
-amin N find -amin 60 현재 디렉토리 아래에 접근한 지 60분 이내의 파일 출력

7. 파일 크기 기반 검색

Option Example Output
-size N find -size 50M 50M인 파일 출력
-size +N -M find -size +50M -100M 50M ~ 100M인 파일 출력 (초과, 미만)

locate

파일, 디렉토리 Index를 만들고, 해당 Index 로 검색을 수행한다.

기본 Index 파일이 생성되는 경로는 /var/lib/mlocate/mlocate.db 이다.

Index에서 검색하므로 가장 빠르다.

Options Example Output
-b \NAME (–basename) locate \input.txt input.txt와 일치하는 이름을 가진 모든 파일/디렉토리를 출력

which, type

셸의 탐색 경로 내에서 명령어의 위치를 찾는다.

Options Output
-a 명령어에 대한 모든 일치하는 바이너리 위치를 출력

whereis

매개변수로 주어진 디렉토리 목록에 대해 탐색한다.

whereis -bm ls tr -m gcc : ls, tr 검색어에 대해 Binary, ManPage 검색 + gcc 검색어에 대해 ManPage 검색

Options Description Output
-b (binary) 검색어에 대응되는 바이너리 검색을 한다
-B,M,S [directories…] -b/m/s 옵션으로 검색 시 탐색할 디렉토리
-m (manual) 검색어에 대응되는 매뉴얼 검색을 한다 (Man Page)
-s (sources) 검색에어 대응되는 소스파일 검색을 한다
-f -B, -M, -S 옵션 사용시 반드시 사용해야 함. 찾을 검색어와 옵션의 구분자 역할을 한다

TODO:

  • find 이외에는 문서가 자세하고 정확한 경우는 잘 없어서 조사가 더 필요할 것 같다.

리눅스 셸(bash) 기본 기능 소개

이 글에서 소개할 내용은 굉장히 유용한 기능이라고 생각하며, 셸의 역할인 코드 실행 시의 입/출력에 대한 Proxy, Middleware 역할을 잘 활용하는 기능들이라고 생각한다. 이 글은 리눅스 핵심 레퍼런스의 일부를 참고해 작성하였다.

기준 환경:

Ubuntu 20.04.1 LTS (GCP Compute Engine)


셸은 단순한 호출보다 훨씬 많은 것을 할 수 있다.


1. wildcard: 정규표현식과 유사한 검색을 수행한 결과를 명령의 입력으로 사용


1. 가장 기본이 되는 예제

이름에 wildcard 검색을 수행해 결과를 명령의 입력으로 사용할 수 있다. 이름 일치 기준은 디렉토리이다. 즉 a*를 셸 명령어에 입력하게 되면, ./a로 시작하는 파일/디렉토리를 반환한다. 특정 상위 폴더나 하위 폴더를 대상으로 검색하고 싶은 경우 그에 맞는 상대 경로를 입력하면 된다.


(ex 1) ls a* == ls aardvark adamantium apple

(ex 2) ls githubblog/.* == ls githubblog/.git githubblog/.deploy_git, ...

기준 디렉토리 목록

위 사진은 기준 디렉토리이다. 여기서 g* 인 파일/디렉토리를 ls -alF의 매개변수로 주려고 한다.

g*에 해당하는 목록을 wildcard를 통해 입력으로 사용

위 사진은 명령의 결과물로, 실제로 잘 수행됨을 확인할 수 있다.


2.추가 옵션

[문자들...] : 문자들 중 하나와 일치하는 경우.

  • [aieou] : 모음 중 하나. 단 이렇게 찾으려면 파일/디렉토리 이름이 a, i, e, o, u 중 하나여야 한다. (즉 한 글자)

[^문자들...], [!문자들...] : 명시된 문자 이외의 any 문자

  • [^aieou] : 자음 중 하나. 단 이렇게 찾으려면 파일/디렉토리 이름이 b, c, d, f, g, … 중 하나여야 한다. (즉 한 글자)

? : 임의의 한 문자. character 하나의 placeholder라고 생각하면 편리하다.

  • [githubblo?] : githubblog가 있다면 일치한다.

* : asterisk의 일반적인 의미처럼 아무거나. empty를 포함한 모든 string을 의미. 보통 조합할 때 필수적으로 사용된다.

  • *[aioeu] : 모음으로 끝나는 경우
  • *[aioeu]* : 모음이 포함된 경우
  • [aioeu]* : 모음으로 시작하는 경우

2. 중괄호 확장: 단순히 가능한 모든 경우의 수를 입력으로 사용

문자열 중간에서 사용되며 가능한 모든 경우의 수로 치환된 후 입력으로 사용된다.

echo a{b,c,d}e{f,g,h} 결과

(ex) echo a{b,c,d}e{f,g,h} == echo abef abeg abeh acef aceg aceh adef adeg adeh


3. 변수: String 타입의 환경 변수

bash 프로파일 관리에 대해선 좀 더 나중에 다루려고 한다.

Windows의 환경 변수와 cmd 환경 변수와 같은 2가지 변수가 있다. 모두 환경 변수이지만 그 범위가 다른데, cmd 환경 변수에 대응되는 Linux에서의 개념이 셸 변수이다. 단 아래의 방법으로 하면 해당 세션(셸)에서만 사용할 수 있으므로 일회성 변수로 생각하면 좋다.

쓰기 : MYVAR=string_value

읽기 : $MYVAR

만약 환경 변수로 저장하고 싶다면, export MYVAR=string_value와 같이 사용하면 된다. 환경 변수는 printenv 혹은 env 명령으로 확인할 수 있다.


기본으로 제공되는 환경 변수

PATH : 바이너리 검색 경로의 목록. 콜론으로 구분.

PWD : 현재 디렉토리 ( OLDPWD : 마지막으로 방문한 디렉토리 )

HOME : 홈 디렉토리 ( ex : /home/sb )

USER : 로그인명 ( sb )


4. alias

단순한 String 치환이다.

지정 : alias ll = "ls -lG"를 입력하면, 이후 셸에서 ll을 입력하면 ls -lG가 입력된다.

목록 확인 : alias만 입력하면 된다.

alias 입력 시의 결과


5. 입출력 redirection

아직 입출력을 파일을 통해 수행해본 적이 없어서 추후 적절한 예시를 추가하려고 한다. 이번 글에서는 개념적으로 그 사용법만 다룬다.

표준 입출력의 지점을 임의의 파일에 수행하게 한다.

입력을 파일의 내용으로 : command < input_file

출력을 파일로 :

  1. 새로운 파일로 작성 : command > output_file

  2. 기존 파일에 이어 쓰기 : command >> output_file

  3. 오류의 경우 : command 2> error_file

  4. 출력, 오류 모두 : command >& output_file 혹은 command &> output_file

  5. 출력, 오류 각각 : command > output_file 2> error_file

리눅스에서 표준 스트림은 3가지이며 자세한 내용은 위키 백과 (표준 스트림) 참고


6. Pipe

  1. 각 프로그램이 하나의 일을 잘 할 수 있게 만들 것. 새로운 일을 하려면, 새로운 기능들을 추가하기 위해 오래된 프로그램을 복잡하게 만들지 말고 새로 만들 것.
  2. 모든 프로그램 출력이 아직 잘 알려지지 않은 프로그램이라고 할지라도 다른 프로그램에 대한 입력이 될 수 있게 할 것. 무관한 정보로 출력을 채우지 말 것. 까다롭게 세로로 구분되거나 바이너리로 된 입력 형식은 피할 것. 대화식 입력을 고집하지 말 것.
  3. 소프트웨어를, 심지어는 운영 체제일지라도 이른 시기에 수주에 걸쳐 이상적으로 시도해가며 설계하고 만들 것. 어설픈 부분을 버리고 다시 만드는 것을 주저하지 말 것.
  4. 프로그래밍 작업을 가볍게 하기 위해, 심지어 우회하는 방법으로 도구를 만들고 바로 버릴지라도 어설픈 도움 보다는 도구 사용을 선호할 것.

출처: 위키 백과 (유닉스 철학)

Pipe 연산자는 유닉스 철학을 구현하는 도구 중 하나로, 이 중 2번 규칙을 지키는 도구로 사용된다.

(ex) who | sort | awk '{print $1}' | less

pipe 연산자의 효과를 제대로 소개하는 예제를 만들기엔 아직 아는 명령어가 극히 적어서 추후 제대로 소개하고자 한다. 해당 소개 글이 작성될 경우 이 글에서 링크를 제공하도록 하겠다.


7. 평가식

평가식이란 그 내용이 코드로 해석되는 영역을 말한다. 셸에서의 평가식은 해당 평가식을 셸에서 따로 실행시켰을 때의 결과를 반환하는 형태를 갖는다. 이 평가식의 문법은 크게 두 가지가 있는데,

  1. backtick : echo This year is ``date +%Y\``
    • This year is 2021
  2. $() : echo Next year is $(expr $(date +%Y) + 1)
    • Next year is 2022

평가식으로 (5)에서 실패했던 echo < sample.txt를 평가식으로는 실행할 수 있다: echo $(cat sample.txt) (`을 사용해도 된다.)


8. 작업 제어

셸에서 수행되는 프로그램은 대개 포그라운드로 실행된다. 즉 사용자와의 인터렉션이 블로킹되는데 셸에서 프로그램을 실행할 때 백그라운드로도 실행시킬 수 있다. 또한 포그라운드와 백그라운드를 넘나들 수 있으며 작업을 정지하고 다시 실행할 수도 있으며 셸 마저 정지할 수도 있다.

백그라운드로 작업 실행 : command ... & (&가 핵심이다.)

포그라운드 작업 정지 : Ctrl + Z

백그라운드에서 작업 재개 : `bg {id}``

포그라운드로 작업을 가져와 실행 : fg {id}

현재 수행 중인 작업의 목록 조회 : jobs

현재 셸 정지 : suspend (현재 실행 중인 셸이 2개 이상이어야 호출 가능하다.)


9. 여러 셸 동시 사용

screen은 내장 기능이어서 dependency가 추가로 필요하지 않아 사용에 제약이 없지만 그 기능이 적고 불편하다. tmux가 많이 사용되며 기본으로 설치되는 경우도 있으나(WSL Ubuntu에는 기본으로 설치돼있다.) 둘 모두 사용해본 적이 없어 추후에 다루도록 한다.


TODO :

입출력 Redirection 적극적으로 활용해보기 (특히 알고리즘 테스트 케이스 수행 시)

screen/tmux 모두 사용해보고 비교하기

리눅스 명령어 더 공부하고, pipe로 효과적인 예 만들기

리눅스 주요 디렉토리의 이름과 의미 정리 (계속 업데이트 예정)

이 글은 리눅스를 처음 시작하는 경우 다른 OS의 디렉토리 구성과의 큰 차이로 인한 불편함을 줄이기 위한 큰 지도이다.


1. Home 디렉토리

크게 2가지 Home 디렉토리가 있다. 이는 사용자에 따라 구분되는데,

  • 일반 사용자: /home/{USER_NAME}
  • 루트 사용자: /root

형태로 사용한다.


2. 시스템 디렉토리

시스템 디렉토리란 사용자 디렉토리를 제외한 (거의) 모든 디렉토리를 말한다. 윈도우에서 Program Files 폴더가 시스템 디렉토리에 포함된다고 생각하면 이 정의에 동의할 수 있을 것이고, Windows, AppData 등의 폴더만 시스템 디렉토리라고 생각한다면 이 정의에 동의하긴 어려울 듯 하다.


일반적인 경로 구성

시스템 디렉토리의 경로 구성


(ex) /usr/local/share/emacs

  • /usr/local : 스코프
  • /share : 카테고리
  • /emacs : 응용 프로그램

경로 구성 요소 - 스코프

스코프는 가장 상위 디렉토리로서 하위 디렉토리인 카테고리나 응용 프로그램이 실행되는 범위를 나타낸다. 다만 구분에 사용되는 명확한 기준은 없고 단지 //usr보다 좀 더 운영 체제에 가까운 근본적인 수준이라는 느낌이라고 한다(출처: 리눅스 핵심 레퍼런스).

스코프의 종류:

  1. / : 리눅스 시스템 파일

  2. /usr : 또 다른 리눅스 시스템 파일

  3. /usr/local : 개인 컴퓨터에서 지역적으로 생성되는 시스템 파일

    (ex) /usr/local/bin : 기본 프로그램이 아닌 경우 주로 여기에 설치된다.


경로 구성 요소 - 카테고리

카테고리는 하위 디렉토리인 응용 프로그램의 목적을 나타낸다.

  1. 실행 파일:

    • bin : 바이너리
    • sbin : 바이너리 (root 사용자 용이어서 root 권한이 필요하다.)
    • lib : 바이너리에서 사용되는 라이브러리
    • Ubuntu 20.04의 경우 / 스코프의 bin, sbin, lib/usr 스코프로의 심볼릭 링크로 돼 있음 (어떤 배포판들이 또 이렇게 돼있는지는 확인 x)
  2. 설정 파일:

    • etc : 시스템 설정 파일
    • init.d, rc.d : 부팅 설정 파일
  3. 문서: doc, info, man, share

  4. HW 관련:

  5. Runtime:

  6. 운영체제 관련:

    • boot ( /boot/vmlinuz ): 커널, 부팅 관련 파일
    • lost+found : 손상된 파일 등 추후 복구를 위한 임시 저장 경로
    • proc : 현재 실행 중인 프로세스 정보. 저용량이며 실시간으로 반영한다.
      • cat /proc/ioports : I/O HW 목록 표시
      • cat /proc/cpuinfo : 프로세서 정보. 코어 단위로 상세 정보를 출력
      • cat /proc/version : OS 버전 정보 표시 (ex: Linux version 4.19.128-microsoft-standard)
      • cat /proc/uptime : ms 단위로 uptime 출력. (uptime 명령어가 더 낫다)
      • ll /proc/{PID} : PID에 대응되는 프로세스의 정보. (많은데 잘 모르겠다)
      • ll /proc/self : 현재 실행중인 프로세스로의 심볼릭 링크 (ex) 1261

이 글은 꾸준히 계속 업데이트될 예정입니다!