Featured image of post [Bash Shell] 02. ls - 파일 목록 출력

[Bash Shell] 02. ls - 파일 목록 출력

ls는 파일 이름을 나열하는 명령이 아니라 파일시스템 메타데이터를 조회하는 창구다. 정렬·표시·필터링 옵션을 그룹별 표로 정리하고, ls -la, ls -lh --sort=size 같은 실전 예시와 GNU/BSD 이식성 함정, ls 출력 파싱 안티패턴을 다룬다.

이 장을 읽기 전에

직전 챕터인 01장: cd, pwd에서 디렉터리를 이동하고 현재 위치를 확인하는 법을 다뤘다. Part 1(셸 기초와 탐색)은 “지금 어디에 있는가"를 아는 것에서 시작해 “여기에 무엇이 있는가"를 아는 것으로 이어지는데, 이 장이 바로 그 두 번째 단계다. 이 장이 전제하는 지식은 cd로 디렉터리를 이동하고 pwd로 현재 경로를 확인하는 법 정도이며, 별도의 파일 편집·셸 스크립팅 지식은 필요 없다. 난이도는 입문이지만, 옵션 조합과 GNU/BSD 이식성 부분은 중급 수준의 실무 감각을 요구한다.

다루지 않는 것: ls는 파일 목록과 메타데이터만 보여줄 뿐 파일 내용은 전혀 열어보지 않는다. 파일 내용을 화면에 출력하는 법은 03장: cat에서 다룬다.

당신의 수준에 맞는 경로

수준읽을 부분핵심 목표
입문개요+정신 모델, 사용법·옵션 표의 기본 예시(1–3번)ls -l, ls -a로 현재 디렉터리의 파일과 숨김 파일을 확인할 수 있다
중급정렬·표시 형식 옵션, 예시 전체크기·수정 시각 기준으로 정렬하고, 사람이 읽기 쉬운 단위로 출력을 가공할 수 있다
심화주의사항·함정, 흔한 오개념GNU/BSD 옵션 차이를 구분하고, 스크립트에서 ls 출력을 파싱하면 안 되는 이유를 설명할 수 있다

개요 + 정신 모델

ls(“list”)는 단순히 파일 이름을 화면에 나열하는 명령이 아니다. 실제로 ls가 하는 일은 디렉터리 안의 각 엔트리마다 파일시스템이 관리하는 메타데이터(inode 번호, 권한 비트, 하드링크 수, 소유자·그룹, 크기, 마지막 수정 시각, 타입)를 커널에 질의해 조회하는 것이다. 파일 이름은 그중 하나의 필드일 뿐이다. 이렇게 생각하면 -l 옵션이 왜 그렇게 많은 정보를 한 줄에 쏟아내는지 자연스럽게 이해된다 — -l은 이름 하나만 보여주던 것을 파일시스템이 실제로 들고 있는 메타데이터 전체로 확장하는 옵션이기 때문이다.

이 정신 모델은 옵션을 외우는 방식도 바꾼다. -a는 “이름이 .으로 시작하는 엔트리를 숨기는 필터를 끄는 것"이고(리눅스에는 진짜 “숨김 속성"이 없다 — 단지 이름 규칙일 뿐이다), -h는 “바이트 크기 필드를 사람이 읽기 쉬운 단위로 재포맷하는 것"이며, --sort-t/-S는 “어떤 메타데이터 필드를 정렬 키로 쓸지 고르는 것"이다. 즉 ls의 옵션 대부분은 새로운 기능을 추가하는 게 아니라, 파일시스템이 이미 들고 있는 메타데이터 중 무엇을 보여주고 어떤 기준으로 줄 세울지를 고르는 스위치에 가깝다.

사용법 · 옵션

기본 문법은 ls [옵션] [파일...]이다. 인자를 생략하면 현재 디렉터리를, 디렉터리를 지정하면 그 안의 내용을, 파일을 지정하면 그 파일 자체의 정보를 보여준다. 옵션은 성격에 따라 정렬·표시 형식·필터링·색상 및 타입 표시로 나뉜다.

정렬 옵션

옵션계열설명
-SGNU/POSIX파일 크기가 큰 순서로 정렬한다
-tGNU/POSIX수정 시각(mtime) 기준 최신순으로 정렬한다
-cGNU/POSIX-t와 함께 쓰면 상태 변경 시각(ctime) 기준으로 정렬한다
-uGNU/POSIX-t와 함께 쓰면 마지막 접근 시각(atime) 기준으로 정렬한다
-XGNU확장자 알파벳 순으로 정렬한다
-vGNU파일명에 포함된 숫자를 자연수 순서(버전 정렬)로 비교한다
-r, --reverseGNU/POSIX정렬 순서를 반대로 뒤집는다
-UGNU정렬하지 않고 디렉터리에 저장된 순서 그대로 출력한다
--sort=WORDGNU정렬 키를 이름으로 지정한다(size, time, version, extension, none 등) — -S/-t/-X와 동등한 장문 표기

표시 형식 옵션

옵션계열설명
-lGNU/POSIX권한·링크 수·소유자·그룹·크기·수정 시각·이름을 한 줄씩 상세 출력한다(long format)
-h, --human-readableGNU-l/-s와 함께 쓰면 크기를 1K, 234M, 2G처럼 사람이 읽기 쉬운 단위로 보여준다
--siGNU-h와 비슷하지만 1024 단위 대신 1000 단위(SI)로 환산한다
-1GNU/POSIX한 줄에 파일 하나씩만 출력한다
-CGNU/POSIX여러 열로 정렬해 세로로 나열한다(기본 형식)
-xGNU/POSIX여러 열로 정렬하되 가로 방향으로 채운다
-mGNU/POSIX파일 이름을 쉼표로 구분해 한 줄로 나열한다
-R, --recursiveGNU/POSIX하위 디렉터리까지 재귀적으로 나열한다
-i, --inodeGNU각 파일의 inode 번호를 함께 출력한다
-s, --sizeGNU/POSIX파일이 차지하는 블록 크기를 함께 출력한다
--full-timeGNU수정 시각을 초 단위까지 생략 없이 전부 출력한다

필터링 옵션

옵션계열설명
-a, --allGNU/POSIX.으로 시작하는 이름(숨김 관례 파일)까지 포함해 전부 보여준다
-A, --almost-allGNU-a와 같지만 ... 두 항목은 제외한다
-d, --directoryGNU/POSIX디렉터리 안의 내용을 나열하지 않고 디렉터리 자체의 정보만 보여준다
-B, --ignore-backupsGNU이름이 ~로 끝나는 백업 파일을 목록에서 제외한다
--hide=PATTERNGNU지정한 패턴과 일치하는 이름을 숨긴다(-a를 함께 쓰면 무시된다)
-I, --ignore=PATTERNGNU지정한 패턴과 일치하는 이름을 항상 제외한다

색상 · 타입 표시 옵션

옵션계열설명
--color[=WHEN]GNU 전용파일 타입별로 색을 입혀 출력한다(never, always, auto)
-GBSD/macOS 전용--color와 동등한 역할을 하는 BSD 계열 옵션
-F, --classifyGNU/POSIX타입을 나타내는 문자를 이름 뒤에 붙인다(디렉터리 /, 실행 파일 *, 심볼릭 링크 @, 소켓 =, FIFO `
-pGNU/POSIX디렉터리 뒤에만 /를 붙인다(-F의 축소판)
--group-directories-firstGNU 전용파일보다 디렉터리를 먼저 나열한다
-L, --dereferenceGNU/POSIX심볼릭 링크가 아니라 링크가 가리키는 실제 대상의 정보를 보여준다

예시

가장 자주 쓰는 조합은 숨김 파일까지 포함해 상세 정보를 보는 것이다.

1
2
# 숨김 파일 포함, 권한·크기·수정 시각까지 상세 출력
ls -la

크기를 바이트 그대로 읽기보다 사람이 읽기 쉬운 단위로 보고 싶을 때는 -h를 더한다.

1
2
# 크기를 KB/MB/GB 단위로, 큰 파일부터 정렬
ls -lh --sort=size

최근에 수정된 파일을 빠르게 확인할 때는 시간순 정렬과 head를 조합한다.

1
2
# 최근 수정된 파일 상위 10개만 확인
ls -lt | head

디렉터리만 골라 보고 싶을 때는 ls의 글로빙과 -d를 함께 쓴다.

1
2
# 현재 위치의 하위 디렉터리 이름만 나열(파일은 제외)
ls -d */

터미널에서 타입을 색으로 구분해서 보려면 명시적으로 색상을 켠다(파이프로 넘기면 자동 감지가 꺼지므로 always가 필요할 때도 있다).

1
2
# 파일 타입별로 색을 입혀 출력
ls --color=auto

재귀적으로 하위 디렉터리까지 전부 훑을 때는 -R을 쓴다.

1
2
# 하위 디렉터리 구조 전체를 재귀적으로 나열
ls -laR ./project

inode 번호는 하드링크가 같은 파일을 가리키는지 확인할 때 유용하다.

1
2
# inode 번호를 함께 출력해 두 이름이 같은 파일을 가리키는지 확인
ls -li file1 file2

디렉터리를 파일보다 먼저 보고 싶다면 GNU 전용 옵션을 추가한다.

1
2
# 디렉터리를 파일보다 먼저 나열(GNU ls 전용)
ls -la --group-directories-first

파일 타입을 문자로 구분해서 스크립트 없이 눈으로 빠르게 훑을 수도 있다.

1
2
# 디렉터리는 /, 실행 파일은 *, 심볼릭 링크는 @로 표시
ls -F

디렉터리 자체의 메타데이터만(내용은 제외) 확인하고 싶을 때는 -d를 단독으로 쓴다.

1
2
# /etc 디렉터리 자체의 권한·소유자 정보만 확인(내부 목록은 생략)
ls -ld /etc

주의사항 · 함정

GNU 전용 옵션은 macOS/BSD ls에서 그대로 쓸 수 없다. --color, --group-directories-first, --sort=WORD 같은 장문 옵션은 GNU coreutils의 확장이다. macOS 기본 ls(BSD 계열)에는 이런 장문 옵션 자체가 없고, 색상 출력은 -G 한 글자 옵션으로 켠다. macOS에 Homebrew로 coreutils를 설치하면 gls라는 이름으로 GNU ls를 함께 쓸 수 있지만, 기본 ls는 여전히 BSD 계열이라는 점을 스크립트를 여러 플랫폼에 배포할 때 반드시 확인해야 한다.

-a, -la...까지 센다. -a를 쓰면 현재 디렉터리(.)와 상위 디렉터리(..)도 목록에 포함된다. ls -la | wc -l으로 “파일 개수"를 세는 스크립트를 짜면 실제보다 최소 2개 많은 값이 나오는 실수가 흔하다. ./..을 빼고 숨김 파일만 보고 싶다면 -A(--almost-all)를 쓰는 편이 안전하다.

ls 출력을 파싱하면 깨진다. 파일 이름에 공백이나 개행이 들어 있으면 ls의 출력을 공백이나 줄바꿈으로 나눠 처리하는 스크립트는 하나의 파일명을 여러 항목으로 잘못 쪼갠다. 이는 셸 스크립팅 커뮤니티에서 “Parsing ls is fragile"이라는 표현으로 잘 알려진 안티패턴이다. 파일 목록을 스크립트에서 안전하게 순회하려면 ls 출력을 파이프로 넘기는 대신 셸의 글로빙(for f in *; do ... done)이나 find ... -print0 + xargs -0처럼 구분자가 명확한 방법을 써야 한다.

1
2
3
4
5
6
7
8
# 안티패턴: 파일명에 공백이 있으면 깨진다
for f in $(ls); do echo "$f"; done

# 안전한 대안 1: 셸 글로빙
for f in *; do echo "$f"; done

# 안전한 대안 2: find + xargs -0 (개행이 있어도 안전)
find . -maxdepth 1 -type f -print0 | xargs -0 -I{} echo {}

흔한 오개념

“숨김 파일"은 실제로 숨겨진 게 아니다. .으로 시작하는 파일은 접근 권한이나 특수 속성이 걸린 게 아니라, ls가 기본적으로 .으로 시작하는 이름을 목록에서 제외하는 표시 관례일 뿐이다. cat .bashrc처럼 이름을 직접 지정하면 -a 없이도 얼마든지 읽고 쓸 수 있다. Windows의 “숨김 속성"과 달리 파일시스템 메타데이터 차원의 숨김이 아니다.

ls -l의 크기 필드가 디스크 사용량과 같은 것은 아니다. -l이 보여주는 크기는 파일의 논리적 바이트 수(파일 끝까지의 오프셋)이지, 파일시스템이 실제로 디스크에 할당한 블록 크기가 아니다. 희소 파일(sparse file)이나 블록 정렬 때문에 둘은 다를 수 있다. 실제 디스크 사용량을 보려면 -s 옵션이나 du 명령을 써야 한다.

다음 장에서는

03장: cat에서는 ls로 확인한 파일의 이름과 메타데이터를 넘어, 그 파일의 실제 내용을 화면에 출력하는 법을 다룬다.

평가 기준

  • ls가 파일 이름 나열이 아니라 파일시스템 메타데이터 조회라는 정신 모델로 -l의 출력 필드를 설명할 수 있다.
  • 목적에 맞게 정렬 옵션(-t, -S, --sort)과 표시 형식 옵션(-h, -1, -R)을 조합할 수 있다.
  • GNU ls와 macOS/BSD ls의 옵션 차이(--color vs -G, 장문 옵션 지원 여부)를 구분할 수 있다.
  • -la./..까지 포함한다는 점과, 개수를 셀 때 -A를 쓰는 이유를 설명할 수 있다.
  • ls 출력을 직접 파싱하면 안 되는 이유를 설명하고, 글로빙이나 find -print0로 대체할 수 있다.

참고