파일 세트의 이름을 바꾸는 Bash 정규식

파일 세트의 이름을 바꾸는 Bash 정규식

rename명령(정규식 사용)을 사용하여 파일 세트의 이름을 바꿔야 합니다 . 몇 번 시도한 후에도 예상한 결과를 얻는 표현식을 찾을 수 없습니다.

다음과 같은 파일 패턴이 있습니다.

접두사_some_name_other.txt

모든 파일은 " prefix_" 문자열로 시작하고 " _other.txt"로 끝납니다.some_name부분은 밑줄로 구분된 여러(영숫자) 단어로 구성될 수 있습니다. 따라서 다음이 가능합니다.

prefix_one_name_other.txt
prefix_this_is_my_name_1_this1_other.txt

파일 이름을 다음과 같이 바꿔야 합니다.

other_one-name_날짜 시간
other_this-is-내 이름-1-this1_날짜 시간

다시 말해서:

  • " "을(를) 삭제해야 합니다 prefix(밑줄은 남겨두고).
  • " other" 토큰은 파일 이름의 시작 부분으로 이동합니다.
  • ~ 안에some_name, 밑줄(_)을 대시(-)로 변환
  • 파일 이름 끝에 밑줄(뒤에some_name)은 남아 있어야 합니다
  • 확장자 를 삭제하고 .txt다음으로 대체해야 합니다.날짜 시간.

내가 시도한 것:

rename 's/fw_([a-z]+)_(\d)_(\w+\d)_(\w+)\.txt/$4_$1-$2-$3_'$datahora'/' *.txt

$datahora가지다날짜 시간값(테스트됨). 이것은 예상대로 작동합니다

prefix_name_1_gnt1_other.txt

하지만 함께는 아니야

prefix_other_name_2_gnt2_other.txt

내가 어디서 잘못됐나요? 내가 또 어떻게 그 일을 성취할 수 있겠는가?

지금은 내가 가지고 있는 모든 파일 이름에 대해 작동하는 정규식을 찾을 수 없기 때문에 마음을 놓았습니다. 문자열의 첫 번째 요소는 항상 부분 prefix이고 마지막 요소는 other.txt문자열의 일부라는 것을 알고 있습니다. 따라서 문자열을 배열로 분할하고 새 이름을 만드는 데 필요한 항목을 얻을 수 있습니다. 사실 그런 것입니다.

datahora="20140718-080000"
arrfiles=( *.txt )
for curfile in ${arrfiles[*]}
do
    arrparts=( ${curfile//_/ } )
    numitems=${#arrparts[*]}
    newname=""
    for (( c=1; c<numitems-1; c++ ))
    do
        newname+="${arrparts[c]}-"
    done
    newname=${newname%-}
    arrparts[numitems-1]=${arrparts[numitems-1]/.txt/}
    newname="${arrparts[numitems-1]}_${newname}_$datahora"
    echo "$curfile pasa a $newname"
    mv ${curfile} ${newname}
done

이런 식으로 수행한 후 @peterph 제안을 다시 시도하고 마지막으로 일부 이름 바꾸기 정규식 조합을 완료했습니다. 다음과 같이 생각합니다.

rename 's/_/-/g' *.txt
rename 's/^fw-(.*)-([^-]*)(\.txt)/$2.$1$3/' *.txt
rename 's/(\w+)\.(.*)(\.txt)/$1_$2_'$datahora'/' *.txt

최선의 접근 방식이 무엇인지 잘 모르겠습니다. 제 생각에는 regex 변형이 더 우아해 보이지만 작업을 수행하려면 세 번의 이름 바꾸기 작업(디스크에 세 번 액세스)이 필요한 반면 변형은 array디스크에 한 번만 씁니다.

¿이 두 가지 솔루션에 대해 어떻게 생각하십니까?...

다시 한 번 감사드립니다.

답변1

rename여러 대체 명령을 받아들일 수 없다면그리고파일 이름의 루트( some_name)에는 밑줄이 두 개 이상 포함될 수 있습니다. 이 작업은 두 단계로 수행해야 합니다. a) 밑줄을 대시로 바꾸고 b) 파일 이름에서 (다시) 청크를 이동합니다.

찾고 있는 정규식은 다음과 같습니다.

rename 's/_/-/g' *.txt
rename 's/^prefix-(.*)-([^-]*).txt$/$2_$1_'$DATETIME'/' *txt

첫 번째는 밑줄을 사용하여 대시 번역을 수행하고 후자는 루트와 접미사를 교환하고 DATETIME환경 변수의 내용을 이름에 추가합니다. 물론 접두사와 확장자는 생략합니다.

해당 [^-]*부분은 대시를 포함하지 않는 모든 문자열과 일치합니다. 접미사가 항상 동일한 경우 접두사의 경우와 같이 그대로 입력할 수 있습니다(반대의 경우도 마찬가지입니다. 접두사가 다를 수 있는 경우 ^[^-]*-파일 시작 부분 사이에 대시가 포함되지 않은 문자열과 일치하도록 사용). 이름과 (따라서) 첫 번째 대시).

rename여러 명령을 지원하는 경우 해당 명령을 연결하면 됩니다.

rename 's/_/-/g;s/^prefix-(.*)-([^-]*).txt$/$2_$1_'$DATETIME'/' *txt

관련 정보