Programming/Bash Shell Script

[Bash Shell Script] (연습 예제) CP 명령어 사용 시 중복된 파일의 이름을 자동으로 변경하기

Nirsa 2021. 5. 21. 12:04
반응형
  • (연습 예제) CP 명령어 사용 시 중복된 파일의 이름을 자동으로 변경하기

배시 쉘 스크립트 연습 예제 입니다. 아래와 같은 상황에서 중복된 파일의 이름을 자동으로 변경해주는 스크립트를 만드는것이 목표 입니다.

  1. /root/test 디렉토리의 jpg 파일을 /root/data/ 으로 복사
  2. /root/test2 디렉토리의 jpg 파일을 /root/data/ 으로 복사
  3. test 디렉토리의 파일과, test2 디렉토리의 파일 중 test1.jpg ~ test5.jpg 파일명이 같음

 

이러한 문제를 해결하기 위해 고민한 부분은 크게 다음과 같습니다.

  1. 파일명을 어떻게 바꿔야 할까? → 랜덤 문자열 생성
  2. 파일명을 변경 시 경로 제외를 어떻게 할까? → awk로 마지막 레코드만 출력 후 변수에 저장
  3. 쉘 스크립트에서 cp 명령어로 파일명이 중복된다는걸 어떻게 캐치할 수 있을까?  → expect 사용

 

가장 문제가 되는것은 파일명 중복을 캐치하는 부분 인데, 파일명이 중복될 경우 "cp: overwrite" 프롬프트가 생성 됩니다. expect를 사용해 cp: overwrite 문자열이 확인될 경우 exit를 반환 합니다.

* expect를 사용하기 위해선 패키지를 설치해야 합니다. (yum -y install expect)

* exp 파일은 sh 명령이 아니라, expect 명령어로 파일을 실행해야 합니다.

* status code를 구분해 중복으로 판단될 경우 네이밍을 하기 위해 exit로 반환 합니다.

저는 아래와 같은 auto_overwrite.exp 파일을 생성 했습니다.

#!/usr/bin/expect -f

# timeout 시간 무제한
set timeout -1

# 쉘 스크립트에서 인자값으로 변수를 받아옴
set after_path [lindex $argv 0]
set item [lindex $argv 1]

# cp 명령 실행
spawn cp -i $item $after_path

# 특정 문자열 발생 시 exit 입력
expect "cp: overwrite* "
send "exit\r"

 

이제 중복 파일명을 확인할 수 있는 expect를 만들었으니, 쉘스크립트로 넘어 갑니다. 저의 경우 root 홈디렉토리 아래를 검색해 jpg로 끝나는 파일들을 file_name 이라는 변수에 배열로 담았습니다.

자세한 내용은 주석 처리한 내용을 확인하시면 됩니다.

#!/bin/bash
after_path="/root/data"
file_name=`find /root -name "*.jpg"`

## file_name의 배열들을 하나씩 꺼내가면서 반복중 실행
for item in ${file_name[*]}
do
	## /root/item-name 파일에 저장 (절대 경로 파일명이 저장됨)
        echo "$item" > /root/item-name
        
        ## 중복 파일을 네이밍하기 위한 랜덤 문자열 생성 후 변수에 저장
        random_name=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | sed 1q)
        
        ## awk로 마지막 레코드(파일명)을 추출 후 변수에 저장
        item_file_name=$(awk -F '/' '{ print $NF }' /root/item-name)
        
        ## 위에서 생성한 exp파일 실행, 뒤에 변수는 인자값 전달
        expect /root/auto_overwrite.exp $after_path $item
        
        ## status code를 변수에 저장
        state=`echo $?`

        ## status code 0 : Overwrite
        if [ "$state" == "0" ]; then
        	## Overwrite가 발생한 경우 중복 파일로 인지하고 네이밍을 새로 진행
                cp "$item" "$after_path"/"$item_file_name"-"$random_name"
        ## status code 1 : Success
        elif [ "$state" == "1" ]; then
                echo "Success"
        fi

		## 생성했던 item-name 파일 삭제
        rm -rf /root/item-name
done

 

스크립트 실행 결과는 아래와 같습니다.

반응형