Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 在以破折号开头的目录中查找_Unix_Shell_Find_Escaping - Fatal编程技术网

Unix 在以破折号开头的目录中查找

Unix 在以破折号开头的目录中查找,unix,shell,find,escaping,Unix,Shell,Find,Escaping,find将文件名开头的破折号解释为选项的开头。使用熟悉的--技巧不起作用,因为选项在文件名之后,引用无效,用\-替换第一个破折号也不起作用。通常鼓励用户在此类文件名前面加上/,但如果我不知道给定的路径是绝对路径还是相对路径,我该怎么办 编辑:一种解决方案是查找“$(readlink-f--“$test\u filename”)”,但它很难看。还有更好的主意吗 编辑2:感谢您的建议。以下是这项工作产生的两个脚本: 如果它在脚本中,您可以随时检查它。例如,对于bash、ksh或zsh: if [[

find
将文件名开头的破折号解释为选项的开头。使用熟悉的
--
技巧不起作用,因为选项在文件名之后,引用无效,用
\-
替换第一个破折号也不起作用。通常鼓励用户在此类文件名前面加上
/
,但如果我不知道给定的路径是绝对路径还是相对路径,我该怎么办

编辑:一种解决方案是
查找“$(readlink-f--“$test\u filename”)”
,但它很难看。还有更好的主意吗


编辑2:感谢您的建议。以下是这项工作产生的两个脚本:

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

if [[ "$DIR" = -* ]]; then
    find ./"$DIR"
else
    find "$DIR"
fi
以更简洁的形式(对于bash、ksh93或zsh):

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

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

这似乎有点便宜,但我建议您使用您已经找到的
readlink
解决方案。据报道,

以a开头的第一个参数 “-”(…)和所有后续参数 应解释为 表情


因此,
--
确实不起作用。thkala的解决方案也可能有效,但我发现它的可读性较差。但是,如果您进行了大量的
查找
调用,它可能会更快。

使用glob捕捉破折号:

find . -name '[-]*'


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

以下是一种适用于所有类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 shells和其他POSIX之前的sh实现缺少算法和
设置--
,因此有点难看

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。它在Mac OS X(从10.6.4开始)、HP-UX(从11.22开始)、Solaris(从OpenSolaris 200906开始)、AIX(从7.1开始)上不可用(除非您已经安装了GNU工具,并且确保它们在您的
路径中)。

在OP编辑之前,我的回答确实涉及到readlink,因为它确实没有我的第一个oneliner那么深奥。它的一个缺点是,它会启动另外两个进程(一个forked shell和readlink本身),如果要查找多个目录作为参数,那么将readlink应用于所有目录至少需要一个循环和一些技巧。@thkala:我自己才知道这一点
$(exec readlink-f--“$file”)
以牺牲可读性为代价阻止其中一个分叉。@larsmans:thkala的答案的优点是在没有
readlink-f
的系统上工作(只有GNU、NetBSD和OpenBSD有)。@Gilles:MacOS X 10.6.4拥有GNU的
readlink
。thkala的解决方案是否也适用于NetBSD外壳(
ash
)?我检查了它是否在Korn Shell中工作。@larsmans:thkala的第一个解决方案需要
[…]]
构造(so bash/ksh/zsh),第二个解决方案需要
${…/…/…}
(so bash/ksh93/zsh)。根据,OSX 10.6.4没有
readlink-f
(它有)。这是globbing,不是正则表达式。@DennisWilliamson它可能是globbing,但它肯定也是正则表达式。有一个(琐碎的)角色类,有连锁,还有一个克莱恩星。如果character类有一个以上的字符,就会有交替,并且它会有所有的东西。但是,我承认,从技术上讲,如果您将任何一系列字符用作正则表达式,那么它都是正则表达式。@ParthianShot:shell将所有
[-]*
处理为全局,而不是正则表达式。这里的星号不是克莱恩星,因为它并不意味着“零或更多”。在glob中,它作为通配符意味着“任何东西”。这里的表达式表示后跟任意序列的连字符,而不是零个或多个连字符。然而,为了防止过早扩张,应该引用它。@DennisWilliamson哦,我知道这一点。我只是学究气;指出它可以被解释为一个有效的正则表达式,不像某些glob。例如,
*
本身就是正则表达式中的语法错误,而在glob中则是有效的。话虽如此,请将您的评论向上投票,因为它是相关的,并且可能有助于有人无意中看到此答案。请注意,
if[“$DIR=-*]
DIR
与文本字符串
-*
匹配(如果当前目录中没有名称以
-
开头的文件)或者可能会导致语法错误(如果有)。@Gilles:true…我不知道自己遇到了什么问题-我从不使用“test”或[在bash中]。
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 "$@" …