Spo*_*pot 0 find cp shell-script
我需要根据经过的时间处理一组文件(因为我无法控制何时将新文件添加到远程目录)。
我必须对这组文件进行多次操作,因此我试图将find
结果存储在一个变量中(因此我可以确保经过的候选不会改变),然后find
对每个操作使用相同的列表(无需再次执行)。
这是我正在尝试的精简版本。
FILELIST=$(ssh ${SSHUSER}@${SSHHOST} "cd ${REMOTEPATH}; find -amin +${TIME} -type f,d -print")
if [[ ${#FILELIST} -lt 4 ]]; then
echo "No files" >> ${LOGFILE}
exit 1
fi
echo -en "Copying remote files to remote backup\n" >> ${LOGFILE}
ssh ${SSHUSER}@${SSHHOST} "cd ${REMOTEPATH}; cp -Rpv '${FILELIST}' ${REMOTEBACKUPPATH}" >> ${LOGFILE}
Run Code Online (Sandbox Code Playgroud)
这当然给了我cp: missing destination file operand after ''
我理解的。我只是不知道如何以cp
喜欢的方式格式化文件列表。
我已经在这方面工作了一段时间,阅读了文档/SE 帖子,但无法弄清楚。我希望一旦我知道我做错了什么,cp
我也可以将这些知识应用于rsync
.
我是 bash 脚本领域的新手,如果还不清楚的话。:)
提前致谢。
bash
不是最好的外壳来处理。我建议zsh
改为(您已经zsh
通过不引用某些参数扩展来使用语法):
filelist=(
${(0)"$(
ssh $SSHUSER@$SSHHOST "
cd -- ${(qq)REMOTEPATH} &&
find . -amin +${TIME} -type f,d -prune -print0"
)"}
)
if (( $#filelist < 4 )); then
print No files >> $LOGFILE
else
print "Copying remote files to remote backup" >> $LOGFILE
print -rNC1 -- $filelist | ssh $SSHUSER@$SSHHOST "
cd -- ${(qq)REMOTEPATH} && xargs -r0 cp -Rpvt ${(qq)REMOTEBACKUPPATH}"
fi
Run Code Online (Sandbox Code Playgroud)
(假设$SSHHOST
是一个 GNU 系统(你自己已经在使用一些 GNUisms 了f,d
,没有文件传递给find
, cp -v
),并且$SSHUSER
那里的登录 shell是类似 Bourne 的)。
我已经添加-prune
了find
命令,因为您将以任何方式复制这些整个目录,因此无论如何都没有必要在那里寻找更多文件。读取这些目录的内容也会更新它们的上次访问时间。
在任何情况下,请注意读取目录中的文件不会更新目录的访问时间。目录的访问时间在读取它自己的内容时更新,就像您在其中使用ls
/find
或 shell glob一样(另请注意,如今,访问时间并不总是得到彻底维护)。所以目前还不清楚你到底想做什么。
以上我们使用:
filelist=( values )
定义一个数组变量(在哪里filelist=value
定义一个标量变量)。${(0)"$(cmd)"}
拆分cmd
NUL 上的输出。使用 NUL 分隔列表是传递文件路径列表的安全方式,因为 NUL 是文件路径中唯一不允许的字符。cd -- ${(qq)REMOTEPATH}
,--
以防止以$REMOTEPATH
开头的值-
(-
虽然不是它本身,但在某些 shell 中也不是-4
/ +3
),并且$REMOTEPATH
引用的值(由此处的本地 shell 扩展)(使用单引号 with qq
,这是唯一安全的方法)对于远程 shell(假设它是类似 Bourne 的,$REMOTEPATH
如果登录 shell$SSHUSER
是 csh/fish/rc... ,则它不适用于某些值)。&&
确保下一个命令仅cd
在成功时运行,否则您将在错误的目录中运行它。-print0
: 打印 NUL 分隔的文件路径(见上文)。$#filelist
将包含匹配文件的数量(我们将其与原始代码中的 4 个进行比较,不知道为什么)。print -N
给ssh
stdin上的NUL 分隔(带),它是继承的在xargs
那里。xargs
读取该列表并将其转换为cp -t target
(-t
也是 GNU 扩展) 的参数。xargs
将cp
根据需要运行尽可能多的s,避免参数大小限制。