0

我在 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

如果是,那么请继续删除;否则什么都不做。

如何将给定的位置与那些固定的字符串进行比较?

4

4 回答 4

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 攻击提供额外的保护。尽管如此,尽早过滤元数据是个好主意。

于 2009-11-10T04:47:03.580 回答
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

于 2009-11-10T04:24:33.907 回答
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了该函数,虽然大多数现代 shell 都有它,但它在 POSIX 中没有指定:您可以更改它以适应您的情况,因为其余的都是符合 POSIX 的。

在 BASH 中,您不必casefor循环中使用:您可以只使用[[which 模式匹配,即:

[[ $f = "$i"/* ]] && return

它也不会分词,也不会执行任何文件名扩展。但是,需要引用"$i"以确保任何通配符(如*?不用通配符)。

于 2012-06-25T07:22:03.247 回答
0

使用sed命令

于 2009-11-10T04:41:02.877 回答