我正在尝试查找可能包含其他可怕字符[方括号]的任意文件。由于我使用-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.
我的“为什么”问题得到了回答;现在,正如我之前所说的那样,“对于任意字符串,我怎样才能避免对某些字符的非字面解释?”
答案 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//\?/\\?}"