Bash - 재귀적 디렉터리/파일 이름 바꾸기

Bash - 재귀적 디렉터리/파일 이름 바꾸기

파일과 디렉터리의 모든 공백을 재귀적으로 바꾸는 다음 스크립트가 있습니다.

################### SETUP VARIABLES #######################
number=0                    # Number of renamed.
number_not=0                # Number of not renamed.
IFS=$'\n'
array=( `find ./ -type d` ) # Find catalogs recursively.


######################## GO ###############################
# Reverse cycle.
for (( i = ${#array[@]}; i; )); do
     # Go in to catalog.
     pushd "${array[--i]}" >/dev/null 2>&1
     # Search of all files in the current directory.
     for name in *
     do
             # Check for spaces in names of files and directories.
             echo "$name" | grep -q " "
             if [ $? -eq 0 ]
             then
                # Replacing spaces with underscores.
                newname=`echo $name | sed -e "s/ /_/g"`
                if [ -e $newname ]
                then
                        let "number_not +=1"
                        echo " Not renaming: $name"
                else
                        # Plus one to number.
                        let "number += 1"
                        # Message about rename.
                        echo "$number Renaming: $name"
                        # Rename.
                        mv "$name" "$newname"
                fi
             fi
     done
     # Go back.
     popd >/dev/null 2>&1
done

echo -en "\n All operations is complited."

if [ "$number_not" -ne "0" ]
  then echo -en "\n $number_not not renamed."
fi

if [ "$number" -eq "0" ]
  then echo -en "\n Nothing been renamed.\n"
elif [ "$number" -eq "1" ]
   then echo -en "\n $number renamed.\n"
   else echo -en "\n Renamed files and catalogs: $number\n"
fi

exit 0

배열을 디렉토리로 채우는 방식으로 작동합니다.

array=( `find ./ -type d` ) # Find catalogs recursively.

이 스크립트를 특정 디렉토리에서 강제로 작동시키려면 그렇게 할 수 있습니까?

array=( `find /my/start/directory/ -type d` ) # Find catalogs recursively.

나는 그것이 올바른지 다시 확인하고 실수로 서버의 모든 파일 이름을 바꾸고 싶지 않기 때문에 (단순히 실행하는 것이 아니라) 여기에 묻습니다!

답변1

mv명령을 주석 처리하고 실행하여 제안된 변경 사항으로 스크립트를 테스트 할 수 있습니다 . 스크립트에서 너무 많은 일이 진행되고 있어 즉시 괜찮다고 말할 수는 없지만 array현재 스크립트가 유효한 경우 혼란스러울 수 있습니다(분명히 개행 문자가 포함된 디렉터리 이름이 없거나 배열이 엉망이 되거나 이름이 시작되지 않음). 대시를 사용 mv하고 echo일부 장소에서는) 괜찮을 것이라고 추측합니다.


디렉터리 및 기타 파일의 파일 이름에서 공백을 밑줄로 반복적으로 바꿉니다.

topdir=.
find "$topdir" -depth -name "* *" -exec bash -c '
    for pathname do
        # $pathname will have at least one space in it
        newname=${pathname##*/}  # get basename
        newname=${newname// /_}  # replace spaces with underscores
        printf "Would move %s to %s\n" "$pathname" "${pathname%/*}/$newname"
        # mv "$pathname" "${pathname%/*}/$newname"
     done' bash {} +

$topdir이름 안이나 아래에 공백이 하나 이상 포함된 모든 항목을 찾습니다 . 이러한 경로 이름을 수집하여 인라인 bash스크립트에 제공합니다. 이 스크립트는 각 경로 이름의 파일 이름 부분을 추출하고 공백을 밑줄로 바꿉니다. 실제 작업은 안전상의 이유로 mv주석 처리되었습니다 .

-depth아직 액세스하지 않은 디렉토리의 이름을 바꾸고 싶지 않기 때문에 이 옵션이 필요합니다. 이를 통해 find디렉터리 계층 구조의 깊이 우선 탐색이 수행됩니다.

사용된 매개변수 대체:

  • ${variable##*/}: 값의 마지막 슬래시 앞의 모든 항목을 제거합니다 variable. 와 거의 동일합니다 $( basename "$variable" ).
  • ${variable%/*}: 마지막 슬래시 뒤의 모든 항목을 제거합니다. 와 거의 동일합니다 $( dirname "$variable" ).
  • ${variable//pattern/replacement}: pattern일치하는 값의 모든 것을 대체합니다(이것은 확장입니다).replacementvariablebash

새 파일 이름이 이미 존재하는지 여부를 확인하지 않습니다. 이는 내부 스크립트에서 쉽게 수행할 수 있습니다 bash.

if [ -e "${pathname%/*}/$newname" ]; then
    printf "Will not rename %s, new name exists\n" "$pathname" >&2
else
    printf "Would move %s to %s\n" "$pathname" "${pathname%/*}/$newname"
    # mv "$pathname" "${pathname%/*}/$newname"
fi

시험:

$ tree
.
|-- a directory
|   `-- yet another file
|-- script.sh
|-- some file
`-- some other file

1 directory, 4 files

$ sh script.sh
Would move ./some file to ./some_file
Would move ./some other file to ./some_other_file
Would move ./a directory/yet another file to ./a directory/yet_another_file
Would move ./a directory to ./a_directory

관련된:

관련 정보