hanker

[리눅스 쉘 스크립트] 디렉터리 내 모든 파일들의 특정 문자열 제거 본문

SERVER/Linux

[리눅스 쉘 스크립트] 디렉터리 내 모든 파일들의 특정 문자열 제거

hanker 2025. 4. 24. 22:48
반응형

리눅스 디렉터리 내 특정 문자열이 포함된 파일들을 찾아서 파일들의 해당 문자열을 제거하고,

다시 파일명을 새로 만들어주는 쉘 스크립트를 만들어보자.

 


1. 구조 및 동작

tree를 사용하여 디렉터리 내 파일들 확인

디렉터리 구조를 보면 디렉터리 내부에 또 디렉터리가 있고 그 안에 파일들이 위치해있다.

우리가 원하는 기능은 최하위 디렉터리 내 파일들까지 파일명을 변경하고자 한다.

 

해당 흐름을 살펴보자

흐름도

1. 사용자가 스크립트를 실행하게 되면, 스크립트는 경로와 제거할 문자열을 사용자에게 요청한다.

2. 디렉터리 내에 모든 파일들을 찾게되고, 해당되는 파일들을 보여준다. 

3. 여기서 사용자가 Y를 누르게 되면 해당 파일들의 문자열이 제거된다.


2. 쉘 스크립트 전체 코드
#!/bin/bash

echo "디렉터리 경로를 입력하세요 (기본: 현재 디렉터리):"
read -r TARGET_DIR
TARGET_DIR="${TARGET_DIR:-.}"

if [[ ! -d "$TARGET_DIR" ]]; then
  echo "디렉터리가 존재하지 않습니다: $TARGET_DIR"
  exit 1
fi

echo "제거할 문자열을 입력하세요 (예: #, sample_):"
read -r REMOVE_STRING

if [[ -z "$REMOVE_STRING" ]]; then
  echo "제거할 문자열이 비어있습니다."
  exit 1
fi

echo
echo "아래 파일들이 변경 대상입니다 (하위 디렉터리 포함):"

FILES_TO_RENAME=()

# 재귀적으로 모든 일반 파일 검색
while IFS= read -r -d '' f; do
  filename=$(basename "$f")
  dirname=$(dirname "$f")

  # 제거할 문자열이 파일명에 포함된 경우
  if [[ "$filename" == *"$REMOVE_STRING"* ]]; then
    NEW_FILENAME="${filename//$REMOVE_STRING/}"
    NEW_PATH="$dirname/$NEW_FILENAME"

    echo "$f → $NEW_PATH"
    FILES_TO_RENAME+=("$f:$NEW_PATH")
  fi
done < <(find "$TARGET_DIR" -type f -print0)

if [[ ${#FILES_TO_RENAME[@]} -eq 0 ]]; then
  echo "변경할 파일이 없습니다."
  exit 0
fi

echo
read -r -p "위 파일들의 이름을 변경하시겠습니까? (Y/N): " CONFIRM

if [[ "$CONFIRM" =~ ^[Yy]$ ]]; then
  echo "이름 변경 중..."
  for pair in "${FILES_TO_RENAME[@]}"; do
    OLD="${pair%%:*}"
    NEW="${pair##*:}"
    mv -i -- "$OLD" "$NEW"
  done
  echo "파일 이름 변경이 완료되었습니다."
else
  echo "작업이 취소되었습니다."
fi

 


3. 코드 설명

 

#!/bin/bash

 

  • bash 쉘 실행 명시  (표준 쉐뱅)

 

echo "디렉터리 경로를 입력하세요 (기본: 현재 디렉터리):"
read -r TARGET_DIR
TARGET_DIR="${TARGET_DIR:-.}"  # 기본값: 현재 디렉터리
  • 사용자에게 디렉터리 경로를 입력받음
  • read 명령어를 사용하여 입력값을 TARGET_DIR 변수에 저장 (-r 옵션은 역슬래시 (\) 같은 특수문자 무시 방지)
  • ${변수:-기본값} : 변수가 비어 있으면 기본값이라는 파라미터 확장 문법. (입력값이 비어 있다면 기본값 .(현재 디렉터리) 사용

 

if [[ ! -d "$TARGET_DIR" ]]; then
  echo "디렉터리가 존재하지 않습니다: $TARGET_DIR"
  exit 1
fi
  • 입력한 경로가 디렉터리인지 확인 아니면 종료
  • -d : 디렉터리인지 확인, ! -d : 디렉터리가 아니면 TRUE

 

echo "제거할 문자열을 입력하세요 (예: #, sample_):"
read -r REMOVE_STRING

if [[ -z "$REMOVE_STRING" ]]; then
  echo "제거할 문자열이 비어있습니다."
  exit 1
fi
  • read 명령어를 사용하여 입력값을 REMOVE_STRING 변수에 저장
  • -z : 옵션은 문자열이 비었는지 확인. REMOVE_STRING 변수가 비어있다면 작업 종료

 

FILES_TO_RENAME=()
  • FILES_TO_RENAME=() : 배열 선언, 나중에 변경할 파일 목록을 보여줄 때 사용

 

# 재귀적으로 모든 일반 파일 검색
while IFS= read -r -d '' f; do
  filename=$(basename "$f")
  dirname=$(dirname "$f")

  # 제거할 문자열이 파일명에 포함된 경우
  if [[ "$filename" == *"$REMOVE_STRING"* ]]; then
    NEW_FILENAME="${filename//$REMOVE_STRING/}"
    NEW_PATH="$dirname/$NEW_FILENAME"

    echo "$f → $NEW_PATH"
    FILES_TO_RENAME+=("$f:$NEW_PATH")
  fi
done < <(find "$TARGET_DIR" -type f -print0)
  • find 명령어로 읽어온 파일 목록을 반복 처리한다.
  • -d '' : null 문자(\0)를 구분자로 사용
  • IFS= : 파일명 내 특수문자 처리하기 위해 내부 필드 구분자를 초기화 해준다.
  • basename : 파일명 추출, dirname은 디렉터리 경로 추출
  • 파일명에 제거 대상 문자열을 포함하고 있는지 확인
  • 문자열을 치환( "${var//OLD/NEW}": 문자열 전체에서 OLD를 NEW로 전부 치환 )하여 REMOVE_STRING 제거
  • 디렉터리 경로와 변경된 파일명을 붙여서 새로운 경로 생성
  • $f : 변경 전 파일, $NEW_PATH : 변경 후 파일
  • "원래경로:새경로" 형식으로 배열에 저장
  • find ... -print0 : 하위 모든 파일을 null 문자로 구분해서 출력

 

if [[ ${#FILES_TO_RENAME[@]} -eq 0 ]]; then
  echo "변경할 파일이 없습니다."
  exit 0
fi
  • 배열 요소가 없으면 변경 대상이 없다고 판단하여 종료

 

echo
read -r -p "위 파일들의 이름을 변경하시겠습니까? (Y/N): " CONFIRM
  • read 명령어를 사용하여 사용자에게 작업 수행 여부를 물어본다. (-p 옵션을 사용하여 메시지를 출력하고 한 줄 입력받음)

 

if [[ "$CONFIRM" =~ ^[Yy]$ ]]; then
  echo "이름 변경 중..."
  for pair in "${FILES_TO_RENAME[@]}"; do
    OLD="${pair%%:*}"
    NEW="${pair##*:}"
    mv -i -- "$OLD" "$NEW"
  done
  echo "파일 이름 변경이 완료되었습니다."
else
  echo "작업이 취소되었습니다."
fi
  • 입력한 값이 Y 또는 y 일 때만 작업을 수행한다. (정규 표현식 ^ : 시작, [Yy] : Y 또는 y, $ : 끝
  • 배열의 개수만큼 반복
  • %%:* 앞부분만 추출 (기존 파일 경로), ##*:  뒷부분만 추출 (새 파일 경로)
  • mv 명령어를 사용하여 파일명 변경 (-i 옵션으로 덮어쓸 때 확인 메시지 출력)

 


4. 실행

 

4-1. vi 에디터로 스크립트 파일 생성 후 권한 변경 ( chmod +x file_rename.sh)

chmod +x file_rename.sh

 

 

4-2. ./file_rename.sh 실행

실행 순서

 

 

4-3. 실행 결과

실행결과

 

 

 

 

 

끝.

 

 

 

 

https://hanke-r.tistory.com/entry/Linux-read-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%9E%85%EB%A0%A5-%EA%B0%92%EC%9D%84-%EB%B3%80%EC%88%98%EC%97%90-%EC%A0%80%EC%9E%A5%ED%95%98%EB%8A%94-%EB%AA%85%EB%A0%B9%EC%96%B4

 

Linux - read 명령어 (입력 값을 변수에 저장하는 명령어)

read 명령어는 표준 입력(키보드 등)으로부터 한 줄(또는 지정한 개수)의 데이터를 읽어 변수에 저장한다.다양한 옵션으로 프롬프트, 타임아웃, 숨김 입력, 구분자 지정 등을 제어할 수 있다.1. 옵

hanke-r.tistory.com

 

https://hanke-r.tistory.com/entry/Linux-%EC%89%98-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B8%B0%EB%B3%B8-%EA%B5%AC%EC%A1%B0-%EB%B0%8F-%EC%83%9D%EC%84%B1-%EC%8B%A4%ED%96%89

 

Linux - 쉘 스크립트 기본 구조 및 생성, 실행

쉘스크립트는 쉘(shell)이라는 커맨드 인터프리터를 이용하여 여러 명령어를 순차적으로 실행하도록 작성된 텍스트 파일이다.주로 리눅스, 유닉스 계열 운영체제에서 시스템 관리, 자동화 작업,

hanke-r.tistory.com

 

반응형