Devin.KR
로그인

리눅스 file 명령어 사용법 - 확장자 없이 파일 종류 확인하기

개발자 조회 2

이 명령어를 언제 쓰는가

file은 파일 내용의 앞부분(매직 넘버)을 읽어 그 파일이 무엇인지 알려준다. 리눅스는 확장자로 파일 종류를 판단하지 않기 때문에, 확장자가 없거나 거짓말하는 파일을 만났을 때 file이 유일한 단서가 된다.

실무에서 자주 만나는 상황은 이렇다. 업로드된 파일이 정말 이미지인지 확인할 때, .tar.gz라고 받았는데 압축이 안 풀릴 때, 스크립트가 bad interpreter로 죽을 때(윈도우 개행 문제), 바이너리가 32비트인지 64비트인지 확인할 때다. 몇 초짜리 확인 한 번이 삽질을 크게 줄인다.

기본 형식

file [옵션] 파일 [파일 ...]

파일명을 여러 개 주면 각각 한 줄씩 출력한다. 출력은 파일명: 판정결과 형식이다.

자주 쓰는 옵션

옵션의미예시
-b파일명을 빼고 판정 결과만 출력(스크립트용)file -b upload.bin
--mime-typeMIME 타입만 출력file -b --mime-type a.jpg
--mimeMIME 타입과 문자셋을 함께 출력file --mime a.txt
-z압축 파일 안쪽 내용까지 들여다본다file -z backup.gz
-L심볼릭 링크를 따라가 대상 파일을 판정file -L /opt/app/current
-s블록·캐릭터 디바이스도 읽는다(파티션 확인)file -s /dev/sda1
-f 목록파일검사할 파일명 목록을 파일에서 읽는다file -f list.txt

실전 예제

1) 확장자를 못 믿을 때 — 받은 파일이 실제로 gzip인지 확인한다.

file backup.tar.gz
# backup.tar.gz: gzip compressed data, last modified: Tue Aug 25 11:57:35 2026, from Unix, original size modulo 2^32 4096

여기서 HTML document text가 나온다면 다운로드가 실패해 에러 페이지를 받은 것이다. 실제로 자주 있는 일이다.

2) 스크립트가 bad interpreter로 죽을 때 — 윈도우에서 편집한 파일의 CRLF 개행이 원인이다.

file deploy.sh
# deploy.sh: Bourne-Again shell script text executable, ASCII text, with CRLF line terminators
sed -i 's/\r$//' deploy.sh     # 개행 정리

3) 바이너리 정보 확인 — 아키텍처가 맞는지, 동적 링크인지 본다.

file /usr/sbin/nginx
# /usr/sbin/nginx: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, stripped

cannot execute binary file 에러가 날 때 여기서 ARM aarch64가 보이면 아키텍처가 다른 바이너리를 받은 것이다.

4) 디렉토리 전체를 훑어 타입별로 세기 — 업로드 디렉토리 점검에 쓴다.

find /var/www/uploads -type f -exec file -b --mime-type {} + \
  | sort | uniq -c | sort -rn

5) 파티션 파일시스템 확인 — 마운트하기 전에 무엇이 들어 있는지 본다.

file -s /dev/sdb1
# /dev/sdb1: Linux rev 1.0 ext4 filesystem data, UUID=... (needs journal recovery) (extents) (64bit)

함정과 주의점

보안 검증을 file에만 맡기지 마라. file은 앞부분 몇 바이트를 규칙과 대조하는 추측이다. 공격자는 파일 앞에 GIF89a를 붙여 놓고 뒤에 실행 코드를 넣을 수 있고, 그러면 fileGIF image data라고 답한다. 업로드 방어는 확장자 화이트리스트, 업로드 디렉토리에서 실행 차단, 원본 파일명 미사용 같은 조치가 본체이고 file은 보조 수단이다.

텍스트 파일의 문자셋 판정은 추측이다. file --mime이 알려주는 charset=utf-8이나 charset=iso-8859-1은 바이트 패턴에서 유추한 값이라, 짧은 한글 파일에서는 틀리기도 한다. 인코딩 변환이 목적이라면 iconv로 변환해 보고 결과를 눈으로 확인하는 편이 확실하다.

심볼릭 링크 기본 동작이 OS마다 다르다. 리눅스의 file은 링크를 따라가지 않아 symbolic link to /opt/app/releases/v2를 출력하지만, macOS는 기본적으로 링크를 따라가 대상 파일의 종류를 출력한다. 어느 쪽인지 확실히 하려면 -L(따라감) 또는 -h(따라가지 않음)를 명시한다.

macOS의 -i는 GNU의 -i와 전혀 다르다. 리눅스에서 file -i a.txttext/plain; charset=us-ascii를 주지만, macOS에서 같은 명령은 regular file만 출력한다. macOS에서 MIME이 필요하면 -I 또는 --mime을 쓴다. 스크립트 이식성이 필요하면 양쪽에서 통하는 --mime-type을 쓰는 게 안전하다.

내용이 없으면 판정도 없다. 0바이트 파일은 empty로 나온다. 전송이 덜 끝난 파일도 앞부분만 맞으면 정상 타입으로 보이므로, 전송 완료 검증은 file이 아니라 크기 비교나 체크섬(md5sum, sha256sum)으로 한다.

함께 보면 좋은 명령어

  • stat — 종류가 아니라 크기·권한·시각 같은 메타데이터가 궁금할 때.
  • strings — 바이너리 안의 문자열을 뽑아낸다. file로 정체를 확인한 다음 단계.
  • hexdump -C — 앞부분 바이트를 직접 본다. file의 판정이 미심쩍을 때 확인용.