我在shell脚本中有一个要求。我从文本文件中获取此位置信息;它总是有效的。
/opt/sasuapps/senny/publish/gbl/SANDHYA/drop1
我需要检查目录是否为空,或者我已经完成了。如果目录不为空,我需要删除该位置下的文件和目录。
作为安全检查的一部分,我想检查从文件(/ opt / sasuapps / senny / publish / gbl / SANDHYA / drop1)获取的放置位置是否以下面的任何一个开头。
/mnt/senny_publish/gbl
/mnt/senny/publish/gbl
/opt/sasuapps/senny/publish/gbl
如果是,则只进行删除;别的什么都不做。
如何比较给定的位置和那些固定的字符串?
答案 0 :(得分:3)
这将适用于bash和任何其他Posix风格的shell,即,对于/ bin / sh不是bash的系统,它是可以的。
check () {
[ "x$1" = x ] && return 1
for pf in /mnt/senny_publish/gbl \
/mnt/senny/publish/gbl \
/opt/sasuapps/senny/publish/gbl; do
suf="${1#$pf}"
[ x"$pf$suf" = x"$1" ] && return 0
done
return 1
}
testcheck () {
echo -n "$1" :
if check "$1"; then
echo OK
else
echo BAD
fi
}
testcheck /how/now
testcheck /not/this
testcheck /mnt/senny_publish/gbl
testcheck /mnt/senny/publish/gbl
testcheck /opt/sasuapps/senny/publish/gbl
testcheck /mnt/senny_publish/gbl/a/b
testcheck /mnt/senny/publish/gbl/a/b
testcheck /opt/sasuapps/senny/publish/gbl/a/b
因此...
/how/now :BAD
/not/this :BAD
/mnt/senny_publish/gbl :OK
/mnt/senny/publish/gbl :OK
/opt/sasuapps/senny/publish/gbl :OK
/mnt/senny_publish/gbl/a/b :OK
/mnt/senny/publish/gbl/a/b :OK
/opt/sasuapps/senny/publish/gbl/a/b :OK
通过避免grep
和其他外部程序,我们将执行完全保留在shell中,避免使用fork和exec,并且还可以提供针对XSS攻击的额外保护。尽管如此,早期过滤metachars是个好主意。
答案 1 :(得分:2)
假设您正在为shell脚本使用bash:
if [ -n "$(echo $LOCATION|grep -lE '/mnt/senny_publish/gbl|/mnt/senny/publish/gbl|/opt/sasuapps/senny/publish/gbl')" ]
then
# Contains one of these paths
else
# Does not contain one of these paths
fi
如果要查看更长的路径列表,可以将它们转储到临时文件中,每行一个,然后使用grep -lEf tempFileWithPaths.txt
答案 2 :(得分:2)
使用case
更清洁:
case $d in
/mnt/foo/gbl/*|/mnt/bar/publish/gbl/*|/opt/sasu/bar/publish/gbl/*)
rm -fr "$d"
esac
..适合日常使用。这符合POSIX标准且速度快。
如果你想把它变成一个函数,你可以这样做:
# prefixed_by "$locn" "$safe_pfx" '/dir/list'
prefixed_by() {
[ -n "$1" ] || return
local i f=$1; shift
for i; do
i=${i%/}
case $f in
"$i/"*) return 0
esac
done
return 1
}
所以,如果你知道,列表中永远不会有空格或通配符(即:它直接在你的脚本中用字符串文字设置),你可以这样做:
readonly safe_list='/mnt/foo/gbl /mnt/bar/publish/gbl /opt/sasu/bar/publish/gbl'
..在初始化时,然后是:
prefixed_by "$d" $safe_list && rm -fr "$d"
我在函数中使用了local
,但在POSIX中没有指定,尽管大多数现代shell都有它:你可以根据自己的情况进行更改,因为其余的都符合POSIX标准。< / p>
在BASH中,您不必在case
循环中使用for
:您可以使用[[
模式匹配,即:
[[ $f = "$i"/* ]] && return
它也不会分词,也不会执行任何文件名扩展。引用"$i"
是必要的,但要确保*
或?
之类的任何通配符都不会用作通配符。
答案 3 :(得分:0)
使用 sed 命令