iBetter Books
수정

파일 테스트와 문자열 비교

실제 스크립트를 작성하다 보면 "이 파일이 있는가?", "이 디렉토리에 쓰기 권한이 있는가?", "이 변수가 비어 있는가?"를 자주 확인하게 됩니다. Bash는 이런 검사를 위한 연산자를 풍부하게 제공합니다.

파일 테스트 연산자

[[ ]] 안에서 사용하는 파일 관련 연산자입니다.

연산자 참인 경우
-e file 파일이나 디렉토리가 존재함
-f file 일반 파일이 존재함 (디렉토리, 링크 제외)
-d file 디렉토리가 존재함
-L file 심볼릭 링크가 존재함
-r file 읽기 권한이 있음
-w file 쓰기 권한이 있음
-x file 실행 권한이 있음
-s file 파일이 존재하고 크기가 0보다 큼
-z file 파일이 존재하고 크기가 0 (빈 파일)
f1 -nt f2 f1이 f2보다 최신 (newer than)
f1 -ot f2 f1이 f2보다 오래됨 (older than)
file="/etc/hosts"[[ -e "$file" ]] && echo "존재함"[[ -f "$file" ]] && echo "일반 파일"[[ -r "$file" ]] && echo "읽기 가능"[[ -w "$file" ]] && echo "쓰기 가능"[[ -x "$file" ]] && echo "실행 가능"[[ -s "$file" ]] && echo "비어있지 않음"

문자열 비교 연산자

연산자 참인 경우
str1 == str2 두 문자열이 같음
str1 != str2 두 문자열이 다름
str1 < str2 str1이 사전순으로 앞에 옴
str1 > str2 str1이 사전순으로 뒤에 옴
-z str 문자열이 비어 있음 (zero length)
-n str 문자열이 비어 있지 않음 (non-zero)
str =~ pattern 문자열이 정규식 패턴에 매칭됨
name="Alice"[[ -z "$name" ]] && echo "비어 있음" || echo "값이 있음"[[ -n "$name" ]] && echo "비어 있지 않음"[[ "$name" == "Alice" ]] && echo "이름이 Alice임"[[ "$name" != "Bob" ]] && echo "Bob이 아님"

<>[[ ]] 안에서만 사용해야 합니다. [ ] 안에서 쓰면 리다이렉션으로 해석될 수 있습니다.

정수 비교 연산자

문자열 비교의 ==는 숫자에도 쓸 수 있지만, 숫자 크기 비교는 전용 연산자를 사용해야 합니다.

연산자 의미
-eq equal (같음)
-ne not equal (다름)
-lt less than (미만)
-le less or equal (이하)
-gt greater than (초과)
-ge greater or equal (이상)
count=10[[ $count -eq 10 ]] && echo "정확히 10"[[ $count -ne 0 ]] && echo "0이 아님"[[ $count -gt 5 ]] && echo "5보다 큼"[[ $count -le 100 ]] && echo "100 이하"

==로 숫자를 비교하면 문자열로 처리되어 "10" == "10" 식으로 비교합니다. 대부분은 맞지만 "10" == "9" 같은 숫자 크기 비교는 문자열 비교로 틀릴 수 있습니다. 크기 비교에는 반드시 -lt, -gt 등을 사용하세요.

실습. 시스템 정보 체크 스크립트

파일과 디렉토리 존재 여부, 권한, 크기를 종합적으로 점검하는 스크립트입니다.

#!/bin/bash# 새 파일: scripts/sys_check.shPASS=0FAIL=0check() {    local desc="$1"    local result="$2"    if [[ "$result" == "ok" ]]; then        echo "[OK]   $desc"        ((PASS++))    else        echo "[FAIL] $desc$result"        ((FAIL++))    fi}echo "=============================="echo "  시스템 점검 시작"echo "=============================="# 필수 파일 확인if [[ -f /etc/hosts ]]; then    check "/etc/hosts 존재" "ok"else    check "/etc/hosts 존재" "파일 없음"fiif [[ -r /etc/hosts ]]; then    check "/etc/hosts 읽기 권한" "ok"else    check "/etc/hosts 읽기 권한" "권한 없음"fi# 홈 디렉토리 확인if [[ -d "$HOME" ]]; then    check "홈 디렉토리 ($HOME) 존재" "ok"else    check "홈 디렉토리 존재" "없음"fiif [[ -w "$HOME" ]]; then    check "홈 디렉토리 쓰기 권한" "ok"else    check "홈 디렉토리 쓰기 권한" "권한 없음"fi# /tmp 확인if [[ -d /tmp && -w /tmp ]]; then    check "/tmp 쓰기 가능" "ok"else    check "/tmp 쓰기 가능" "실패"fi# 환경변수 확인if [[ -n "$HOME" ]]; then    check "\$HOME 설정됨 ($HOME)" "ok"else    check "\$HOME 설정됨" "미설정"fiif [[ -n "$PATH" ]]; then    check "\$PATH 설정됨" "ok"else    check "\$PATH 설정됨" "미설정"fi# 파일 크기 확인logfile="/var/log/syslog"if [[ -f "$logfile" ]]; then    if [[ -s "$logfile" ]]; then        size=$(du -sh "$logfile" 2>/dev/null | cut -f1)        check "$logfile 크기 ($size)" "ok"    else        check "$logfile 크기" "빈 파일"    fielse    check "$logfile 존재" "파일 없음"fiecho "=============================="echo "결과: 통과 ${PASS}개, 실패 ${FAIL}개"echo "=============================="[[ $FAIL -eq 0 ]] && exit 0 || exit 1

실행 결과는 다음과 같습니다.

$ bash scripts/sys_check.sh
==============================
  시스템 점검 시작
==============================
[OK]   /etc/hosts 존재
[OK]   /etc/hosts 읽기 권한
[OK]   홈 디렉토리 (/home/ubuntu) 존재
[OK]   홈 디렉토리 쓰기 권한
[OK]   /tmp 쓰기 가능
[OK]   $HOME 설정됨 (/home/ubuntu)
[OK]   $PATH 설정됨
[OK]   /var/log/syslog 크기 (2.1M)
==============================
결과: 통과 8개, 실패 0개
==============================

$ echo $?
0

check 함수는 설명과 결과 문자열을 받아 출력 형식을 통일합니다. 함수는 PART 05에서 자세히 다루지만, 반복되는 출력 패턴을 줄이기 위해 미리 사용했습니다.

((PASS++)) 는 PART 03에서 배운 산술 연산입니다. 성공할 때마다 PASS를 하나씩 늘립니다.

04. 파일 테스트와 문자열 비교 — 실전 Bash 쉘 프로그래밍 | iBetter Books