我想找到“旧”文件夹/volume1/photo/ipcam这些文件被命名为“????-??-??”,并将 dropbox 中的相应文件夹(具有相同的目录结构 /ipcam/...)移动到子文件夹/ipcam/存档下面的 find 命令(使用适当的值代替变量)在命令行中使用时可以正常工作,但在脚本中使用时则不行:
通过命令行:
find /volume1/photo/ipcam -maxdepth 1 -type d -name "????-??-??" -mtime +0 -exec sh -c 'echo /home/pi/Dropbox-Uploader/dropbox_uploader.sh move /ipcam/$(basename {}) /ipcam/archive' \;
通过脚本:
#!/bin/bash
path2disc="/volume1"
source="$path2disc/photo/ipcam"
dropboxtool="/home/pi/Dropbox-Uploader/dropbox_uploader.sh"
dropbox="/ipcam"
dropboxarchive="/ipcam/archive"
find $source -maxdepth 1 -type d -name "????-??-??" -mtime +0 -exec sh -c '$dropboxtool move $dropbox/$(basename {}) $dropboxarchive' \;
我认为“脚本”版本中的引号有问题,但不确定。
PS:在raspberrypi上使用以下版本: Linux raspberrypi 3.10.24+ #614 PREEMPT 星期四 十二月 19 20:38:42 GMT 2013 armv6l GNU/Linux
答案1
我认为“脚本”版本中的引号有问题,但不确定。
是的,有些地方不对:单引号内的变量不会被替换。在某些情况下,只需将单引号改为双引号即可。不是正确的事情尽管。
在评论中您说-exec sh -c "$dropboxtool move $dropbox/$(basename {}) $dropboxarchive" \;
有效。但这段代码仍然有严重缺陷。
问题:
永不嵌入
{}
shell 代码!这会产生命令注入漏洞。find
机械地替换{}
然后sh -c
解释结果(以及其余参数),可能是代码。类似地,如果你让当前 shell 替换嵌入在 shell 代码中的变量,那么
sh -c
结果可能会被解释为代码。带有;
、>
或等字符的变量|
可能会完全改变即将执行的内容。你不应该这样做,除非:- 从变量注入代码是你明确想要的;
- 或者您绝对确定扩展的变量是安全的,但即便如此,这也不是一个好的做法。
引用应该引用的内容:
$source
(就find
在你的原始代码之后)应该用双引号引起来。- 引用有两种级别。一般来说,某些字符串应该被引用在调用的 shell 上下文中
find
。这意味着到达的选项参数sh -c
(在外壳删除外部引号之后)应该包含一些引号,否则在某些情况下代码将会中断。
您的代码应该看起来更像这样:
find "$source" -maxdepth 1 -type d -name "????-??-??" -mtime +0 -exec sh -c \
'"$1" move "$2/$(basename "$4")" "$3"' \
find-sh "$dropboxtool" "$dropbox" "$dropboxarchive" {} \;
这里$1
,,,和不会被当前 shell 扩展,因为它们是单引号$2
($3
$4
$( )
外部引号很重要)。整个单引号字符串到达sh -c
,然后这些标记才会被扩展。请注意,它们在此级别被正确双引号括起来。当前 shell 或 by 需要替换的所有内容都会find
作为位置参数传递给内壳find-sh
(解释这里),代码本身是静态的。