동일한 접두사를 공유하는 일괄 이름 바꾸기 파일

동일한 접두사를 공유하는 일괄 이름 바꾸기 파일

내 서버에 중복 항목을 제거하려는 접두어가 포함된 파일 목록이 있습니다. 이들은 완전히 다른 makefile입니다.

생성된 파일인 것 같습니다.

{Title} - {yyyy-MM-dd}_{random} - {Description}.ts

예를 들어:

Camera Recording - 2023-08-11_14 - Front Deck.ts
Camera Recording - 2023-08-11_14 - Back Deck.ts
Camera Recording - 2023-08-16_27 - Front Deck.ts
Camera Recording - 2023-08-16_36 - Front Deck.ts
Camera Recording - 2023-08-17_56 - Front Deck.ts

다음 파일 이름에 대한 중복 접두사를 식별하는 스크립트를 실행할 수 있어야 합니다. 그런 다음 날짜 뒤의 숫자 접두사 {random} 부분을 변경하십시오.

Camera Recording - 2023-08-11_14 - Front Deck.ts
Camera Recording - 2023-08-11_14 - Back Deck.ts

다음과 같이 되기 위해서는 {random}을 다른 값(14 제외)으로 바꿔야 합니다.

Camera Recording - 2023-08-11_14 - Front Deck.ts
Camera Recording - 2023-08-11_68 - Back Deck.ts

Linux 쉘 스크립트를 사용하여 이를 달성하는 방법에 대한 제안 사항이 있습니까?

답변1

파일 이름에 개행 문자가 포함될 수 없으면 POSIX awk를 사용하십시오.

$ cat tst.sh
#!/usr/bin/env bash

while IFS= read -r file; do
    if (( cnt++ % 2 )); then
        echo mv -- "$old" "$file"
    fi
    old="$file"
done < <(
    printf '%s\n' *.ts |
    awk '
        match($0,/ - [0-9]{4}(-[0-9]{2}){2}_[0-9]+ - /) {
            beg = substr($0,1,RSTART+13)
            pfx = substr($0,RSTART+14,RLENGTH-17)
            end = substr($0,RSTART+RLENGTH-3)

            maxPfx[beg] = ( pfx > maxPfx[beg] ? pfx : maxPfx[beg] )
            key = beg RS pfx
            ends[key,++cnt[key]] = end
        }
        END {
            for ( key in cnt ) {
                split(key,begPfx,RS)
                beg = begPfx[1]
                for ( i=2; i<=cnt[key]; i++ ) {
                    pfx = begPfx[2]
                    end = ends[key,i]
                    printf "%s%s%s\n", beg, pfx, end
                    pfx = ++maxPfx[beg]
                    printf "%s%s%s\n", beg, pfx, end
                }
            }
        }
    '
)

$ ./tst.sh
mv -- Camera Recording - 2023-08-11_14 - Back Deck.ts Camera Recording - 2023-08-11_15 - Back Deck.ts

위 코드는 문자열(날짜 포함)의 기존 가장 높은 접두사 번호보다 큰 1부터 시작하는 새로운 접두사 번호로 중복 항목을 이동합니다. 임의의 숫자를 새 접두사로 사용할 수 없습니다. 그렇지 않으면 기존 접두사와 동일한 새 접두사가 생길 수 있습니다.

테스트 완료 후 삭제합니다 echo.

답변2

여기에 해결책이 있습니다. Bash 5 이상이 필요합니다.

#!/bin/bash
declare -A SEEN
for FN in *.ts; do
    if [[ $FN =~ ('Camera Recording - ')([0-9]{4}-[0-9]{2}-[0-9]{2}_)([0-9]+)( .*) ]]; then
        BEFORE=${BASH_REMATCH[1]}
        DATE=${BASH_REMATCH[2]}
        RNDM=${BASH_REMATCH[3]}
        AFTER=${BASH_REMATCH[4]}

        KEY=$DATE$RNDM
        if [[ $BASH_VERSION < '5.2.0' ]]; then
            # Workaround for a bug in Bash fixed in 5.2.0
            KEY=${KEY@Q}
        fi
        while [[ -n ${SEEN[$KEY]} && $RNDM -lt 1000 ]]; do
            (( ++RNDM ))
            KEY=$DATE$RNDM
        done
        SEEN[$KEY]=1

        NEW_FILENAME=$BEFORE$DATE$RNDM$AFTER
        if [[ $FN != "$NEW_FILENAME" ]]; then
            mv -iv -- "$FN" "$NEW_FILENAME"
        fi
    fi
done

{random} 필드를 다시 무작위화하지 않고 단지 증가시킬 뿐입니다.

관련 정보