批量重命名共享相同前缀的文件

批量重命名共享相同前缀的文件

我的服务器上有一个文件列表,其中包含我想要删除重复的前缀。这些是完全不同的生成文件。

它似乎是生成的文件

{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 shell 脚本实现这一点有什么建议吗?

答案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} 字段,而只是增加它。

相关内容