find
将文件名开头的短划线解释为选项的开头。使用熟悉的--
技巧不起作用,因为选项位于文件名之后,引用无效,并且用\-
替换第一个短划线也不起作用。通常鼓励用户在./
之前添加这些文件名,但如果我不知道给定路径是绝对路径还是相对路径,我该怎么办?
编辑:一个解决方案是find "$(readlink -f -- "$test_filename")"
,但它很难看。有更好的想法吗?
编辑2 :感谢您的建议。以下是这项工作产生的两个脚本:safe-find.sh; safe-count-files.sh
答案 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(仅影响某些边缘情况)。