bash 스크립트를 사용하여 파일 이름을 일괄적으로 바꾸는 방법은 무엇입니까?

bash 스크립트를 사용하여 파일 이름을 일괄적으로 바꾸는 방법은 무엇입니까?

디렉터리에 다음 형식의 파일이 여러 개 있으므로 모든 파일의 이름을 다음과 같이 바꾸고 싶습니다.

~에서

27_07_2017file1vc001vpxd-1605.log
27_07_2017case2vc001vpxd-9169.log
27_07_2017server3vc001vpxd-4640.log
27_07_2017file24vc001vpxd-9170.log
27_07_2017files5vc001vpxd-4641.log

도착하다

file1vc001vpxd-1605_27_07_2017_1.log
case2vc001vpxd-9169_27_07_2017_1.log
server3vc001vpxd-4640_27_07_2017_1.log
file24vc001vpxd-9170_27_07_2017_1.log
files5vc001vp-4641_27_07_2017_1.log

파일 형식을 datefilename.log다음에서 변경해야 합니다.filename.date_1.log

rename내 Linux 서버에서는 작동하지 않으므로 명령을 제안하지 마십시오 .

감사해요

답변1

이것은 bash 스크립트입니다(일반적인 상황에 맞게 수정됨OP의 수정된 질문을 기반으로 함):

for file in ./*.log; do 
    echo mv "$file" "${file:12:$((${#file}-16))}_${file:2:10}_1.log";
done

위는 ${file:X:Y}bash 하위 문자열 확장 구문 ${variable:offset:length}이며 다음을 얻습니다.길이문자 수오프셋그것 variable(또는 인수) 에서 mv명령을 사용하여 이름을 바꿉니다. echo결과가 원하는 결과라고 확신하면 삭제하면 됩니다.

위의 결과는 다음과 같습니다.

mv ./27_07_2017case5.log case5_27_07_2017_1.log
mv ./27_07_2017file1vc001vpxd-1605.log file1vc001vpxd-1605_27_07_2017_1.log
mv ./27_07_2017file2vc001vpxd-9169.log file2vc001vpxd-9169_27_07_2017_1.log
mv ./27_07_2017file3vc001vpxd-4640.log file3vc001vpxd-4640_27_07_2017_1.log
mv ./27_07_2017file4vc001vpxd-9170.log file4vc001vpxd-9170_27_07_2017_1.log
mv ./27_07_2017file5.log file5_27_07_2017_1.log
mv ./27_07_2017file5vc001vpxd-4641.log file5vc001vpxd-4641_27_07_2017_1.log
mv ./27_07_2017number-blahblahblah5.log number-blahblahblah5_27_07_2017_1.log
mv ./27_07_2017number-blahblahblah5AAABBC.log number-blahblahblah5AAABBC_27_07_2017_1.log
mv ./27_07_2017number5.log number5_27_07_2017_1.log

답변2

귀하의 경우에는 두 가지 구성 요소가 있습니다. 파일 이름그리고날짜

재귀 검색을 사용하여 모든 로그 파일 나열

find "$(pwd)" -type f -iname "*.log" > loglist

하위 디렉터리로 반복하지 않고 모든 로그 파일 나열

find "$(pwd)" -maxdepth 0 -type f -iname "*.log" > loglist

이제 while루프를 사용하여 파일을 원하는 형식으로 이동할 수 있습니다

while read f;
do
    # filename only and not complete path
    fname_only=$(basename "$f");
    
    # directory name only without filename
    dirname_only=$(dirname "$f");
    
    # use cut command to extract first 10 characters as date from filename
    date_only=$(echo "$fname_only" | cut -c 1-10);

    # use cut command to extract 11th character onward as new filename with extension
    fname_extract=$(echo "$fname_only" | cut -c 11-);

    # filename with complete path without extension 
    fname_no_extns="${fname_extract%.*}"

    # Now, move files to their desired format recursively
    mv "$f" "${dirname_only}/${fname_no_extns}.${date_only}_1.log"

done < loglist

답변3

나는 파일 이름에 대해 가능한 모든 경우를 알지 못하므로 귀하의 필요에 맞게 조정할 수 있는 일반적인 접근 방식을 보여 드리겠습니다.

루프를 사용하여 파일을 반복 for하거나 find -exec필요에 따라 반복할 수 있습니다. 나는 주로 파일 이름을 여러 조각으로 자르고 다양한 방법으로 합치는 방법을 알고 싶어한다고 생각합니다.

유사한 도구에 이름을 연결 sed하고 정규 표현식을 생성하여 필요한 부분을 식별할 수 있습니다.

newname=`echo "$oldname"|sed -E 's/([0-9-]{10})(.*).log/\2_\1_1.log/'`

이러한 부품을 주변에 배치 하면 ()교체 문자열에서 등 으로 참조할 수 있습니다 \1. \2조정이 필요한 경우 페이지를 읽어보고, 조정이 되지 않으면 여기에서 문의하세요 man.sed

또 다른 가능성은 POSIX 변수 확장을 사용하는 것입니다.

당신은 알 수도 있습니다

${oldname#*201?}

파일 이름에서 날짜 접두어를 제거합니다( ?모든 문자와 일치할 수 있으므로 충분하다면 2010년부터 2019년까지 작동합니다. 그렇지 않으면 조정하세요.)

다음과 같이 결합할 수도 있습니다.

${oldname%${oldname#*201?}}

위에서 추출한 부분은 제거되므로 날짜만 표시됩니다. 이렇게 하면 파일 이름의 일부를 분리하여 다른 순서로 붙여넣을 수 있습니다.

답변4

필수 zsh + zmv 답변:

autoload -Uz zmv
zmv -n '(<1-31>_<1-12>-<1900-2999>)(*).log' '$2.${1}_1.log'

만족스러우면 삭제합니다 -n(테스트 실행용).

관련 정보