我的服务器上有一个文件列表,其中包含我想要删除重复的前缀。这些是完全不同的生成文件。
它似乎是生成的文件
{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} 字段,而只是增加它。