for 루프
반복해야 할 대상이 명확할 때 for 루프를 씁니다. 파일 목록, 숫자 범위, 텍스트 파일의 항목들, 이 모두를 for 루프로 순회할 수 있습니다.
리스트 순회
가장 기본적인 형태입니다. 공백으로 구분된 항목들을 하나씩 꺼내 처리합니다.
for item in 사과 바나나 딸기; do echo "과일: $item"done
실행 결과는 다음과 같습니다.
과일: 사과
과일: 바나나
과일: 딸기
범위 순회
{시작..끝} 형식으로 숫자 범위를 지정합니다.
# 1부터 5까지for i in {1..5}; do echo "번호: $i"done# 1부터 10까지 2씩 증가 (홀수)for i in {1..10..2}; do echo -n "$i "doneecho
실행 결과는 다음과 같습니다.
번호: 1
번호: 2
번호: 3
번호: 4
번호: 5
1 3 5 7 9
{시작..끝..증분} 형식으로 증분을 지정할 수 있습니다. 음수 증분으로 역순도 가능합니다. {10..1..-1}이면 10, 9, 8... 순으로 출력합니다.
C 스타일 for 루프
C 언어처럼 초기화, 조건, 증감식을 명시하는 방식입니다. 복잡한 반복 제어가 필요할 때 유용합니다.
for ((i=0; i<5; i++)); do echo "i = $i"done# 짝수만 출력for ((i=0; i<=10; i+=2)); do echo -n "$i "doneecho
실행 결과는 다음과 같습니다.
i = 0
i = 1
i = 2
i = 3
i = 4
0 2 4 6 8 10
(( )) 안에서는 $를 붙이지 않고 변수명을 바로 씁니다. PART 03의 산술 연산과 같은 규칙입니다.
글로빙으로 파일 순회
*를 이용해 특정 패턴에 맞는 파일들을 자동으로 목록으로 만들 수 있습니다.
# 현재 디렉토리의 모든 .txt 파일for file in *.txt; do echo "처리 중: $file"done# 하위 디렉토리 포함for file in **/*.sh; do echo "$file"done
주의할 점이 있습니다. 해당 패턴에 맞는 파일이 하나도 없으면 *.txt가 문자 그대로 $file에 들어갑니다. 안전하게 처리하려면 조건 검사를 추가합니다.
for file in *.txt; do [[ -f "$file" ]] || continue # 실제 파일이 아니면 건너뜀 echo "처리 중: $file"done
명령 치환으로 목록 만들기
명령의 출력 결과를 리스트로 사용할 수 있습니다.
# 파일에서 항목 읽기for user in $(cat /etc/passwd | cut -d: -f1); do echo "사용자: $user"done# 명령 출력 결과 순회for pid in $(pgrep bash); do echo "Bash PID: $pid"done
파일을 읽을 때 항목에 공백이 있다면 명령 치환 방식은 공백에서 잘릴 수 있습니다. 공백이 있는 행을 처리할 때는 while IFS= read -r을 사용하는 것이 더 안전합니다. 이 방법은 다음 절에서 다룹니다.
실습. 파일 일괄 이름 변경 스크립트
현재 디렉토리의 .txt 파일을 .bak 확장자로 복사하는 스크립트입니다.
#!/bin/bash# 새 파일: scripts/bulk_rename.shsource_ext="${1:-txt}"target_ext="${2:-bak}"count=0skipped=0echo "변환: .$source_ext → .$target_ext"echo "-----------------------------"for file in *."$source_ext"; do if [[ ! -f "$file" ]]; then echo "대상 파일이 없습니다 (*.${source_ext})" exit 0 fi newname="${file%.$source_ext}.$target_ext" if [[ -f "$newname" ]]; then echo "[SKIP] $file → $newname (이미 존재)" ((skipped++)) continue fi cp "$file" "$newname" echo "[OK] $file → $newname" ((count++))doneecho "-----------------------------"echo "완료: ${count}개 변환, ${skipped}개 건너뜀"
실행 결과는 다음과 같습니다.
$ touch note.txt report.txt readme.txt
$ bash scripts/bulk_rename.sh txt bak
변환: .txt → .bak
-----------------------------
[OK] note.txt → note.bak
[OK] readme.txt → readme.bak
[OK] report.txt → report.bak
-----------------------------
완료: 3개 변환, 0개 건너뜀
$ bash scripts/bulk_rename.sh txt bak
변환: .txt → .bak
-----------------------------
[SKIP] note.txt → note.bak (이미 존재)
[SKIP] readme.txt → readme.bak (이미 존재)
[SKIP] report.txt → report.bak (이미 존재)
-----------------------------
완료: 0개 변환, 3개 건너뜀
${file%.$source_ext}는 파일명에서 확장자 부분을 제거하는 매개변수 확장입니다. %는 접미사를 제거합니다. 예를 들어 note.txt에서 .txt를 제거하면 note가 남습니다.
${1:-txt}는 첫 번째 인자가 없으면 txt를 기본값으로 사용하라는 의미입니다. 인자를 생략하면 .txt → .bak 변환이 기본 동작이 됩니다.