특정 파일 / 디렉토리 바꾸기 (쉘스크립트 포함)

프로그래밍/BASH SHELL|2015. 1. 27. 10:04
반응형

This file is README.txt 

######################################### 
## 
## 스크립트명 : renameto(특정 파일/디렉토리를 바꾸기) 
## 
## 작성자 : 김칠봉 <san2(at)linuxchannel.net> 
## 작성일 : 2003.10.22 pathed for FreeBSD 
##          2002.11.05 add upcase and lowcase, usage to stderr 
##          2002.04.13 patch(sort) 
##          2002.03.29 patch(thanks '단n키') 
##          2002.03.27 add options 
##          2002.03.04 
## 
## 라이센스 : GNU GPL 
## 다운로드 : http://www.linuxchannel.net/devel/renameto/ 
## 
## 
########################################## 

########################################## 
##                                      ## 
## WARNING !!!                          ## 
## 사용자의 사용상 부주의로 인한 피해는 ## 
## 어떠한 경우라고 본 작성자에게 그 책임## 
## 이 없음을 미리 공지합니다.           ## 
##                                      ## 
########################################## 

[기능] 

 - 특정 문자열의 파일을 찾아서 바꿈 
 - 특정 문자열의 디렉토리를 찾아서 바꿈 
 - 바꾸기 전에 view 기능 제공 
 - 특정 디렉토리에서 검색가능 
 - 현재디렉토리, 모든 서브디렉토리, 특정 깊이의 디렉토리 검색 
 - 대소문자 바꾸기 


[사용법] 

# renameto --help 
usage : renameto [options] "/from_string/to_string/" "<target_files|target_directory>" 
  options 
    -R                : include all sub directory (not default) 
    -Rn               : 'n' is sub directory maxdepth number 
                        '-R0' is current directory (same as not given options) 
    -t,-test,--test   : only test view 
    -c,-case,--case   : translate upcase and lowcase 
    -v,-view,--view   : only test view 
    -d,-dir,--dir     : only directory adjust (not files) 
    -h,-help,--help   : help 
  example 
    renameto /html/php/ "*.html" (same as rename command) 
    renameto -R "/ /_/" "* *.mp3" (replace file " " to "_" all sub-directory) 
    renameto -R -test "/ /_/" "* *.mp3" (test view) 
    renameto -R -dir "/ /_/" "/home/xxx/mp3/* *" (replace directory) 
    renameto -R -case "/[A-Z]/[a-z]/" "*" (to lowcase) 
    renameto -R -case "/[e-k]/[E-K]/" "*" (to upcase) 

source download http://ftp.linuxchannel.net/devel/renameto/ 


-R 
  하위의 모든 디렉토리에서 검색 

-R0 
  현재 디렉토리에서만 검색 

-Rn 
  현재디렉토리에서 그다음 n단계 디렉토리까지만 검색, n은 ([0-9]*) 

-R 
  옵션이 없다면 현재디렉토리에서 만 검색 

-d, -dir, --d, --dir 
  파일대신 디렉토리에 적용 
  이 옵션이 없다면 기본적으로 파일을 그 대상으로 함 

-v, -view, --view, -t, -test, --test 
  파일이나 디렉토리를 바꾸지 않고 그냥 찾아서 출력만 함(확인할때) 
  이 옵션이 없다면 매치되는 파일이나 디렉토리를 찾아서 바꿈. 

-c, --case 
  대문자->소문자 or 소문자->대문자 

'/from_string/to_string/' 
  from_string -> to_string 으로 교체 
  공백 문자열이 들어갈 수 있으므로 받드시 전체를 ' 나 "로 묶어줌 
  양자의 구분자는 / 로 구분 

'찾을 디렉토리나 파일 대상' 
  받드시 전체를 ' 나 "로 묶어줌 
  "* *" : 공백 문자열이 들어간 모든 파일이나 디렉토리 대상 
  "*" : 모든 파일이나 디렉토리 대상 
  "*.mp3" : 확장자(?)가 mp3인 모든 파일 
  "*.[hH][tT][mM][lL]" : *.html *.HTML *.Html ... 등과 매치 
  "/home/*.php" : /home 디렉토리를 대상으로 *.php 파일 
  "home/*.php" : 현재 디렉토리에서 상대 경로가 home 인 디렉토리 


[사용예 1] 

/sdb1/mp3 디렉토리 및 그 하위 모든 디렉토리에서 
mp3 파일이나 MP3 파일을 대상으로 
파일이름에 공백(" ")이 들어갈 경우 "_" 로 바꿈 

 먼저 테스트해 봄 

 $ renameto -R --test '/ /_/' '/sdb1/mp3/* *.[mM][pP]3' 
 ... 
 ... 
 $ 

 리스트가 나오면 --test 옵션을 빼고 실행함 

 $ renameto -R '/ /_/' '/sdb1/mp3/* *.[mM][pP]3' 
 ... 
 ... 
 $ 

 -R 
   대상디렉토리(/sdb1/mp3) 및 그 하위의 모든 디렉토리 포함 

 --test 
   단지 테스트만 해봄 

 '/ /_/' 
   공백을 "_"으로 바꾸기 

 '/sdb1/mp3/* *.[mM][pP]3' 
   /sdb1/mp3/ 는 찾을 디렉토리의 시스템 절대경로 
   * *.[mM][pP]3 은 공백 문자열이 들어간 파일의 표현식 


[사용예 2] 

 공백문자 없애기 

 $ renameto '/[ ]//' '*.mp3' 
 또는 
 $ renameto '/ //' '*.mp3' 

 특수문자들 " ( ) * . 없애기 
 $ renameto '/["()*.]//' '*.mp3' 

 특수문자들 [ ] 없애기 
 $ renameto '/[][]//' '*.mp3' 

 확장자 바꾸기 
 $ renameto '/.MP3$/.mp3/' '*.MP3' 

 파일이름 앞에 'My' 문자열 추가하기 
 $ renameto '/^/My/' '*.mp3' 

 파일이름 끝에 'My' 문자열 추가하기 
 $ renameto '/$/My/' '*.mp3' 


[사용예 3] dot(.) 문자 없애기 

 틀린예 : 
 $ renameto '/.//' '*' 

 맞는경우 : 
 $ renameto '/[.]//' '*' 
 또는 
 $ renameto '/.//' '*' 


[사용예 4] 대소문자 바꾸기 

 틀린예 : 
 $ renameto '/[A-Z]/a-z/' '*' (-c 옵션이 빠져있음) 
 $ renameto '/[A-Z]/a-d/' '*' (문자클래스 범위가 맞질않음) 

 대문자 -> 소문자로 바꾸기 
 $ renameto -c '/[A-Z]/a-z/' '*' 
 or 
 $ renameto -c '/[A-Z]/[a-z]/' '*' 

 소문자 -> 대문자 바꾸기 
 $ renameto -c '/[a-z]/A-Z/' '*' 
 or 
 $ renameto -c '/[a-z]/[A-Z]/' '*' 

 특정 클래스(E-K) 알파벳문자 바꾸기 
 $ renameto -c '/[E-K]/e-k/' '*' 
 $ renameto -c '/[e-k]/E-K/' '*' 


[사용예 5] 문자클래스 그룹화 

 모든 대문자 다음에 '_' 문자 추가하기 
 $ renameto '/([A-Z])/1_/' '*' 

 첫번째 공백에 '-' 추가하기 
 $ renameto '/^([^ ]+) /1-/' '*' 


[사용예 6] 종합예제 : mp3 파일 정리 

  $ ls 
  01 aaa.mp3 
  02 bbb (b1).mp3 
  03 ccc Abcd efg.MP3 
  04 ddd bdefgg DDD.mp3 
  05 eee kkk.MP3 
  ... 

  위와 같은 형식을 취하는 여러개의 파일들을 

  artist-[00]-aaa_bbb_ccc.mp3 

  이와같이 형식으로 바꾸려면(대문자->소문자), 

  1. 대문자를 모두 소문자로 바꾸기 
  $ renameto -c '/[A-Z]/a-z/' '*.[mM][pP]3' 

  2. 첫번째 공백을 ']-' 문자로 바꾸기(그룹화 사용) 
  $ renameto '/^([^ ]+) /1]-/' '*.mp3' 

  3. 모든 파일앞에 'artist-[' 문자 추가 
  $ renameto '/^/artist-[' '*' 

  4. 나머지 모든 공백을 '_'로 바꾸기 
  $ renameto '/[ ]/_/' '*' 

  5. 특수문자 괄호 (, )를 없애기(필요하다면) 
  $ renameto '/[()]//' '*' 

  6. 확인 
  $ ls 
  artist-[01]-aaa.mp3 
  artist-[02]-bbb_b1.mp3 
  artist-[03]-ccc_abcd_efg.mp3 
  artist-[04]-ddd_bdefgg_ddd.mp3 
  artist-[05]-eeekkk.mp3 
  ... 


*주의) 
가능한 특수문자는 [와 ]사이에 넣어서 
테스트(-t, --test)를 한 다음에 실행 하세요. 

--------------------------------------------- 


#!/bin/sh 
## 
## "Chilbing, Kim"<san2(at)linuxchannel.net> 
## 2003.10.22 patched for FreeBSD 
## 2002.11.05 add upcase and lowcase, usage to stderr 
## 2002.04.13 patch(sort) 
## 2002.03.29 patch(thanks '단n키') 
## 2002.03.27 add options 
## 2002.03.04 
## 
## http://ftp.linuxchanel.net/devel/renameto/ 
## 
## chmod a+rx renameto 
## cp renameto /usr/local/bin/renameto 

usage() 

echo "${T_MD}usage${T_ME} : renameto [options] "/from_string/to_string/" "<target_files|target_directory>"" >&1 
echo "  ${T_MD}options${T_ME}" >&2 
echo "    -R                : include all sub directory (not default)" >&2 
echo "    -Rn               : 'n' is sub directory maxdepth number" >&2 
echo "                        '-R0' is current directory (same as not given options)" >&2 
echo "    -t,-test,--test   : only test view" >&2 
echo "    -c,-case,--case   : translate upcase and lowcase" >&2 
echo "    -v,-view,--view   : only test view" >&2 
echo "    -d,-dir,--dir     : only directory adjust (not files)" >&2 
echo "    -h,-help,--help   : help" >&2 
echo "  ${T_MD}example${T_ME}" >&2 
echo "    renameto /html/php/ "*.html" (same as rename command)" >&2 
echo "    renameto -R "/ /_/" "* *.mp3" (replace file " " to "_" all sub-directory)" >&2 
echo "    renameto -R -test "/ /_/" "* *.mp3" (test view)" >&2 
echo "    renameto -R -dir "/ /_/" "/home/xxx/mp3/* *" (replace directory)" >&2 
echo "    renameto -R -case "/[A-Z]/[a-z]/" "*" (to lowcase)" >&2 
echo "    renameto -R -case "/[e-k]/[E-K]/" "*" (to upcase)" >&2 
echo "source download ${T_MB}http://ftp.linuxchannel.net/devel/renameto/${T_ME}" >&2 
exit 0 


testing() 

echo "${1}: found '$2'(${T_MG}${4}${T_ME})" 


action() 

echo "${1}: renamed to '${T_MG}${3}${T_ME}'" 
mv "$2" "$3" 


## set color 
## source '/etc/sysconfig/init' 
## 
case $TERM in 
xterm|xterm*|vt220|vt220*|linux) 
T_MG=`echo -e "33[1;32m"` ## bold green 
T_MB=`echo -e "33[1;34m"` ## bold blue 
T_MR=`echo -e "33[1;31m"` ## bold red 
T_MD=`echo -e "33[1;39m"` ## bold white 
T_ME=`echo -e "33[0;39m"` ## normal white 
;; 
default) 
T_MG='' 
T_MB='' 
T_MR='' 
T_MD='' 
T_ME='' 
;; 
esac 

## check_argument number 
## 
[ "$#" -lt "2" ] && usage 

## get options 
## 
for ARGS in $* ; do 
case "$ARGS" in 
-R*) 
  SUB_DIR=$ARGS 
  ;; 
-t*|-v*|--t*|--v*) 
  CMD=testing 
  ;; 
-c*|--c*) 
  CASE=1 
  ;; 
-d*|--d*) 
  TYPE=d ## patch 2002.03.29 
  SORT="-r" 
  ;; 
-h*|--h*) 
  usage 
  ;; 
-*) 
  : ;; 
*) 
  unshift=1 
  ;; 
esac 

[ X"$unshift" = "X" ] && shift 
done 

STRING=$1 
TARGET_FILES=$2 

## recheck argument number 
## 
[ "$#" -lt "2" ] && usage 

## check sub_dir 
## 
if [ X"$SUB_DIR" = "X" ] ; then 
MAXDEPTH="-maxdepth 1" ## current directory search 
else 
MAXDEPTH=`echo "$SUB_DIR" | sed 's/^-R//'` 
if [ `echo "$MAXDEPTH" | egrep "[^0-9]"` ] ; then 
echo "${T_MR}invalid option($SUB_DIR) argument !!!, ex) -R, -R0, -R1, -R2, -R3, ...${T_ME}" >&2 
usage 
fi 

## if $MAXDEPTH is null, then all sub directorys search 
## 
if [ X"$MAXDEPTH" != "X" ] ; then 
maxdepth=$(($MAXDEPTH + 1)) 
MAXDEPTH="-maxdepth $maxdepth" 
fi 
fi 

## check string 
## patch 2002.03.29 
## 
check_string=`echo "$STRING" | egrep "^/([^/]+)/([^/]*)/$"` 
if [ X"$check_string" = "X" ] ; then 
echo "${T_MR}invalid string($STRING) !!!${T_ME}" >&2 
usage 
fi 

## check target_files 
## 
if [ X"$TARGET_FILES" = "X" ] || [ `echo $TARGET_FILES | grep "^-"` ] ; then 
echo "${T_MR}invalid target_file($TARGET_FILES) !!!${T_ME}" >&2 
usage 
fi 

## check find path 
## 
if [ X"`echo $TARGET_FILES | grep /`" != "X" ] ; then 
## same as find_path=`echo "$TARGET_FILES" | sed 's//([^/]*)$//'` 
## 
find_path=${TARGET_FILES%/*} 
find_path=${find_path:-/} ## recheck, patch 2002.03.29 

## same as TARGET_FILES=`echo "$TARGET_FILES" | awk -F"/" '{print($NF)}'` 
## 
TARGET_FILES=${TARGET_FILES##*/} 
fi 

## get from string, to string 
## 
from_string=`echo "$STRING" | awk -F"/" '{print($2)}'` 
to_string=`echo "$STRING" | awk -F"/" '{print($3)}'` 

## check upcase, lowcase translate 
## not good(bad checking T.T) 
## 
if [ X"$CASE" = "X1" ] ; then 
from_tr=`echo "$from_string" | sed 's/[][]//g'` 
to_tr=`echo "$to_string" | sed 's/[][]//g'` 
if [ X$(echo "$from_tr" | tr A-Z a-z) != X$(echo "$to_tr" | tr A-Z a-z) ] ; then 
echo "${T_MR}invalid string($STRING) !!!${T_ME}" >&2 
usage 
fi 
fi 

## lists of files 
## 
files=`find ${find_path:-.} -name "$TARGET_FILES" -type ${TYPE:-f} $MAXDEPTH | sort $SORT 2>/dev/null` 

## good idea 
## 
IFS_ORIG="$IFS" 
IFS=' 


i=0 
for pfile in $files ; do 

## same as file=`basename $pfile` 
## 
file=${pfile##*/} 

## same as path=`echo "$pfile" | sed 's//([^/]*)$//'` 
## 
path=${pfile%/*} 

## if include ${from_string} string in $file, then action 
## 
if [ X$(echo "$file" | grep "$from_string") != "X" ] ; then 
i=$(($i+1)) 
if [ X"$CASE" = "X1" ] ; then 
tofile=`echo "$file" | tr "$from_tr" "$to_tr"` 
else 
## do not sed 's/$AAA/$BBB/g', you must sed "s/$AAA/$BBB/g" 
## 
tofile=`echo "$file" | sed "s${STRING}g"` 
fi 
${CMD:-action} "$i" "$pfile" "$path/$tofile" "$tofile" 
fi 
done 

IFS="$IFS_ORIG" 

exit 0
 


반응형

'프로그래밍 > BASH SHELL' 카테고리의 다른 글

[vi] 특정 단어부터 끝까지 지우기  (0) 2015.01.27
간단한 쉘 스크립트의 작성  (0) 2015.01.27
bash 프롬프트 howto  (0) 2015.01.27
grep 계열 명령어  (0) 2015.01.27
정규표현식  (0) 2015.01.27

댓글()