我使用 Synology 作为闭路电视摄像机影片的存储。将文件从 CCTV 系统复制到 Synology 后,我将其转换为 AVI 格式。所以我的文件的名称如下:
10.01.07-10.01.48[M][@0][0].dav.avi
我想从上面的名称递归地重命名它,如下所示:
10.01.07-10.01.48.avi
请注意,每个文件名始终包含相同的部分[M][@0][0].dav.avi
rename
但问题是Synology shell 中没有命令(sh
不是bash
)
我尝试find
以许多不同的语法使用命令,但没有成功。你能帮我找到解决方案吗?
答案1
你可以这样做:
find . -name '*\[M]\[@0]\[0].dav.avi' -type f -exec sh -c '
for file do
echo mv "$file" "${file%"[M][@0][0].dav.avi"}.avi"
done' sh {} +
(echo
如果看起来没问题,请删除)。
或者,如果您想将所有.dav.avi
重命名为.avi
,但还要删除[M][@0][0]
if :
find . -name '*.dav.avi' -type f -exec sh -c '
for file do
new=${file%.*.*}
new=${new%"[M][@0][0]"}.avi
echo mv "$file" "$new"
done' sh +
这些是 POSIX 语法,也可以与 busybox 实用程序一起使用,因此应该可以在 Synology 上使用。
一些注释(基于您自己和其他答案的观察):
- 传递给的模式
find -name
必须加引号,否则它可能会被 shell 扩展。 xargs
除非您能保证这些文件名不包含空格、换行符、引号或反斜杠,否则不能在文件名上使用。- 使用
printf
代替echo
输出任意数据。 - 在列表上下文中保留未加引号的变量扩展具有非常特殊的含义。你不想在这里这样做。
- 该
.
字符是一个特殊的正则表达式运算符,如果您希望按字面意思处理它,则需要在正则表达式中对其进行转义。 - 读取一行的语法
read
是IFS= read -r line
,但同样不能保证文件路径仅由一行组成。 (cd -P -- "$dir" && find . ... -exec)
这样做通常比这样做更好,find -- "$dir" ... -exec
因为它避免了恰好$dir
是find
谓词或以 and 开头的值的问题-
,因为它缩短了传递到的文件路径-exec
,从而允许传递更多内容。
答案2
这是使用sed
重命名文件的快速解决方案:
echo "10.01.07-10.01.48[M][@0][0].dav.avi" | sed 's/\[.*dav//'
10.01.07-10.01.48.avi
虽然我对 Synology shell 一无所知,但我希望它sed
可用!
在循环中使用(例如):
#!/bin/sh
for file in *avi; do
newName=$(echo "$file" | sed 's/\[.*dav//')
mv -v "$file" "$newName"
done
前:
ls
09.01.07-13.11.48[M][@0][0].dav.avi
110.01.07-13.11.48[M][@0][0].dav.avi
12.01.07-13.11.48[M][@0][0].dav.avi
运行脚本:
./renameAvi.sh
”09.01.07-13.11.48[M][@0][0].dav.avi” -> ”09.01.07-13.11.48.avi”
”110.01.07-13.11.48[M][@0][0].dav.avi” -> ”110.01.07-13.11.48.avi”
”12.01.07-13.11.48[M][@0][0].dav.avi” -> ”12.01.07-13.11.48.avi”
后:
ls
09.01.07-13.11.48.avi 12.01.07-13.11.48.avi
110.01.07-13.11.48.avi
编辑:
如果你想使用find
一实现方式如下:
find . -name "*.avi" | while read fileName; do newName=$(echo "$fileName" | sed 's/\[.*dav//'); mv -v "$fileName" "$newName"; done
”./01.01.07-13.11.38[M][@0][0].dav.avi” -> ”./01.01.07-13.11.38.avi”
”./01.01.07-13.11.39[M][@0][0].dav.avi” -> ”./01.01.07-13.11.39.avi”
sed --version
sed (GNU sed) 4.2.2
find --version
find (GNU findutils) 4.4.2
答案3
对于递归文件重命名,您应该使用以下命令。
find . -name "*dav.avi" | while read fileName; do newName=$(echo "$fileName" | sed 's/\[.*dav//'); mv -v "$fileName" "$newName"; done
从上面的脚本更改
(我无法添加上面的评论,因此在此处添加答案,并对 maulinglawns 已经提到的脚本进行小改动)
- 用于搜索 *dav.avi,因为您的 Synology 存储中将有许多递归文件,因此一旦重命名此文件,就应该再次重命名。
- 这是一个很小的更改,但如果您的实际系统有约 GB 的数据文件,则会产生影响。
答案4
最后我找到了解决方案。重命名分两步完成。这是因为其他闭路电视录像机可能会传输具有不同名称但始终为 DAV 格式的文件。因此,只需添加与第二行类似的附加行,就可以与其他类型的记录器配合:
find $katalog -type f -name *.dav.avi | sed -e "p;s/.dav.avi/\.avi/" | xargs -n2 mv 2>/dev/null
find $katalog -type f -name *.avi | sed -e "p;s/\[M\]\[@0\]\[0\].avi/\.avi/" | xargs -n2 mv 2>/dev/null