我有一台 IP 摄像头,它会将录像保存到我的 Samba 共享中。我想在完全保存后将这些文件复制到其他位置。
现在我的问题是:相机需要一些时间将.avi
格式为(名为motion-date.avi
)的文件复制到我的共享位置,同时它还会创建一个同名的.idx
文件(名为motion-date.idx
),完成后该文件将被删除。
所以我想将所有.avi
没有对应.idx
文件的文件复制到不同的文件夹。
答案1
find /source/dir/ -type f -name '*.avi' -exec sh -c 'test ! -f "${1%.*}.idx" && cp "$1" /target/dir/' sh {} \;
此命令查找.avi
下的所有文件/source/dir/
并为每个文件生成一个基本 shell。然后,shell 会测试是否存在相应的文件,并在需要时.idx
调用。cp
编辑:我稍微修改了命令,使其更加万无一失。根据明确要求,我更详细地解释了整个命令。
find
- 寻找…/source/dir/
–...在给定的目录中...-type f
…所有文件…-name '*.avi'
– …名称符合以下模式…-exec
– ...对找到的每个文件执行...sh -c '…' sh {}
– ...执行命令的 shell;在 shell 内部,路径可用为$1
,因为{}
会被替换为找到的特定文件的实际路径(这就是find -exec
工作原理)。\;
– 这表明了-exec
结束的地方。
每个 shell 都有-c
一个选项,告诉它执行下一个参数,就像输入命令一样。命令如下:
test
– 相应地测试并返回退出状态;以下参数将告诉要测试什么。!
– 注意:测试是相反的。-f
– 测试是否存在现有文件..."${1%.*}.idx"
– ...在此路径下。该${1%.*}
构造告诉 shell 获取参数的内容,而不获取从最后一个点.
到末尾的片段。我附加了另一个扩展名。这样我就交换了它们。
&&
– 仅当前一个命令(即test
)返回退出状态时0
……cp
- …复制…"$1"
– …已找到的文件find
…/target/dir/
– …到目标目录。
最后说明:
- 我需要一个 shell 来处理
"${1%.*}.idx"
和&&
。如果我想复制找到的每个文件,那么… -exec cp {} /target/dir/ \;
就足够了(虽然远非最佳,但我们不要分心)。 - 引用(例如
""
)每条路径是很好的可能包括空格,特殊字符等。 - 的参数(命令)
sh
是单引号(''
)。如果是双引号(""
),则 的扩展"${1%.*}.idx"
将发生在当前 shell(运行 的 shellfind
)中,而这不是我想要的。您可以阅读更多这里。