在以dash开头的目录中查找

时间:2010-11-26 14:23:47

标签: unix shell find escaping

find将文件名开头的短划线解释为选项的开头。使用熟悉的--技巧不起作用,因为选项位于文件名之后,引用无效,并且用\-替换第一个短划线也不起作用。通常鼓励用户在./之前添加这些文件名,但如果我不知道给定路径是绝对路径还是相对路径,我该怎么办?

编辑:一个解决方案是find "$(readlink -f -- "$test_filename")",但它很难看。有更好的想法吗?

编辑2 :感谢您的建议。以下是这项工作产生的两个脚本:safe-find.sh; safe-count-files.sh

4 个答案:

答案 0 :(得分:6)

如果它在脚本中,您可以随时检查它。例如。对于bash,ksh或zsh:

if [[ "$DIR" = -* ]]; then
    find ./"$DIR"
else
    find "$DIR"
fi

以更简洁的形式(对于bash,ksh93或zsh):

find "${DIR/#-/./-}"

您甚至可以使用脚本的参数执行此操作,如果它们都应该是目录:

find "${@/#-/./-}"

答案 1 :(得分:5)

这可能看起来有点便宜,但我实际上推荐您已经找到的readlink解决方法。根据{{​​3}},

  

以a开头的第一个参数   ' - '(...)以及所有后续参数   应解释为   表达

所以--确实无效。 thkala的解决方案也可以使用,但我发现它的可读性较差。但是,如果你正在进行大量的find调用,它可能会更快。

答案 2 :(得分:3)

这种方法适用于所有类Unix系统,不需要特定的shell或非标准的实用程序¹。

case $DIR in
  -*) DIR=./$DIR;;
esac
find "$DIR" …

如果你的位置参数中有一个目录列表并想要处理它们,那就有点复杂了。这是一个POSIX sh解决方案:

i=1
while [ $i -le $# ]; do
  case $1 in
    -*) x=./$1;;
    *) x=$1;;
  esac
  set -- "$@" "$x"
  shift
  i=$(($i + 1))
done
find "$@" …

Bourne shell和其他pre-POSIX sh实现缺少算术和set --,所以它有点丑陋。

i=1
while [ $i -le $# ]; do
  x=$1
  case $1 in
    -*) x=./$1;;
  esac
  set a "$@" "$x"
  shift
  shift
  i=`expr $i + 1`
done
find "$@" …

¹ readlink -f可用于GNU(Linux,Cygwin等),NetBSD≥4.0,OpenBSD≥2.2,BusyBox。它是不可用的(除非你已经安装了GNU工具,并确保它们在你的PATH中)在Mac OS X上(从10.6.4开始),HP-UX(截至11.22) ,Solaris(自OpenSolaris 200906起),AIX(自7.1起)。

答案 3 :(得分:0)

使用glob来捕捉破折号:

find . -name '[-]*'

编辑:更新以删除短语正则表达式,并引用glob,使其由find解释,而不是bash(仅影响某些边缘情况)。