使用-iwholename查找名称中带括号的文件

时间:2014-01-02 21:21:55

标签: unix escaping find string-matching

我正在尝试查找可能包含其他可怕字符[方括号]的任意文件。由于我使用-iwholename,我假设find按字面意思处理-iwholename个参数,但以下内容仅在括号被转义时才有效。

 $ touch [aoeu]
 $ ls
    [aoeu]
 $ find ./ -type f -iwholename ./[AOEU]
 $ find ./ -type f -iwholename ./\\[AOEU\\]
    ./[aoeu]

我找到了this answer,但是它正在谈论正则表达式,我并不想使用它。我只是尝试了一点;我也意识到find正在做其他我不期望的事情:

 $ touch \*aoeu\*
 $ ls
[aoeu]  *aoeu*
 $ find ./ -type f -iwholename ./\*AOEU\*   # I don't expect this expansion.
./*aoeu*
./[aoeu]
 $ find ./ -type f -iwholename ./\\\*AOEU\\\*            
./*aoeu*

对于任意字符串,如何避免某些字符的非字面解释?为什么会这样?

编辑:

总是很高兴再次阅读'ecing manpage'。这次我找到了我之前错过的东西:

  -iwholename pattern
          Like -wholename, but the match is case insensitive.

   -wholename pattern
          See -path.    This alternative is less portable than -path.

   -path pattern
          File name matches shell pattern pattern.  The metacharacters do not treat `/' or `.' specially; so, for example,
                    find . -path "./sr*sc"
          will print an entry for a directory called `./src/misc' (if one exists).  To ignore a whole directory tree, use -prune rather than checking every file in the tree.  For example, to skip the directory `src/emacs' and all files and directories under it, and print the names of the other files found, do something like this:
                    find . -path ./src/emacs -prune -o -print
          Note that the pattern match test applies to the whole file name, starting from one of the start points named on the command line.  It would only make sense to use an absolute path name here if the relevant start point is also an absolute path.  This means that this command will never match anything:
                    find bar -path /foo/bar/myfile -print
          The predicate -path is also supported by HP-UX find and will be in a forthcoming version of the POSIX standard.

我的“为什么”问题得到了回答;现在,正如我之前所说的那样,“对于任意字符串,我怎样才能避免对某些字符的非字面解释?”

1 个答案:

答案 0 :(得分:2)

在BSD的man find页面中,我看到:

-path pattern
         True if the pathname being examined matches pattern.  Special
         shell pattern matching characters (``['', ``]'', ``*'', and
         ``?'') may be used as part of pattern.  These characters may be
         matched explicitly by escaping them with a backslash (``\'').
         Slashes (``/'') are treated as normal characters and do not have
         to be matched explicitly.

-path-wholename相同,-iwholename-path相同,但不区分大小写)

你必须转义这些字符,因为它们对shell有特殊意义。对于-name-iname等其他标记,这是相同的。

要使find使用任意字符串,您需要转义这些特殊字符,例如:

escaped=$(sed -e 's/[][?*]/\\&/g' <<< "*aoeu*")
find ./ -iwholename "$escaped"

<强>更新

正如您自己想象的那样,如果您需要每秒更换大量模式,那么使用bash进行替换会更高效,而不是每次都产生sed,例如这样:

filename_escaped="${filename//\[/\\[}"
filename_escaped="${filename_escaped//\]/\\]}"
filename_escaped="${filename_escaped//\*/\\*}"
filename_escaped="${filename_escaped//\?/\\?}"