在使用find命令时遇到了如下的error:
>find . -name *.java
find: paths must precede expression: staticBlock.java
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
但
>find . -name \*.java
./objectConvert.java
./webservice/SingleFileHTTPServer.java
./webservice/input.java
./StringMain.java
./staticBlock.java
这里的\有什么作用呢??
原来是这样:
[user@localhost perl]$ set -x; find . -name *.pl
+ find . -name fun.pl json_parser.pl login_client.pl test_perl.pl test_perl_withoutM.pl xmlParser.pl
find: paths must precede expression: json_parser.pl
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
++ printf '\033]0;%s@%s:%s\007' user localhost '~/workspace/perl'
[user@localhost perl]$ find ./ -name fun.pl
+ find ./ -name fun.pl
./fun.pl
++ printf '\033]0;%s@%s:%s\007' user localhost '~/workspace/perl'
[user@localhost perl]$ set -x; find . -name \*.pl
+ set -x
+ find . -name '*.pl'
./fun.pl
./json_parser.pl
./login_client.pl
./test_perl.pl
./test_perl_withoutM.pl
./threads/join.pl
./threads/test.pl
./threads/thread.pl
./xmlParser.pl
++ printf '\033]0;%s@%s:%s\007' user localhost '~/workspace/perl'
使用set -x就发现,find 这个命令显示被shell 解析了一遍,然后将模式匹配后的文件名交给find命令来执行。 但如果这个命令我们放到当前目录的父目录,且目录中没有以.pl结尾的文件时,就会发现第一条命令是可以执行成功的,为什么?因为*在模式匹配文件时,如果没有匹配到文件名,就以字符出现,所以在交给find命令执行时,它仍然是个字符*号(参见shopt nullglob).
[superman@localhost workspace]$ shopt -s nullglob[superman@localhost workspace]$ cd ../
[superman@localhost workspace]$ ls *.pl 空
[superman@localhost workspace]$ set -x; find . -name *.pl
+ find . -name
find: missing argument to `-name'
++ printf '\033]0;%s@%s:%s\007' localhost '~/workspace'
[superman@localhost workspace]$ shopt -u nullglob
+ shopt -u nullglob
++ printf '\033]0;%s@%s:%s\007' localhost '~/workspace'
[superman@localhost workspace]$ set -x; find . -name *.pl+ set -x
+ find . -name '*.pl'
./perl/fun.pl
./perl/json_parser.pl
./perl/login_client.pl
./perl/test_perl.pl
./perl/test_perl_withoutM.pl
./perl/threads/join.pl
./perl/threads/test.pl
./perl/threads/thread.pl
./perl/xmlParser.pl
++ printf '\033]0;%s@%s:%s\007' localhost '~/workspace'
由此可见,当find中使用通配符时,通配符先是被shell处理一遍,然后再交给find命令来执行。
http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=4099773&pid=24009926&page=1&extra=#pid24009926
附录:
set 用法:
set [+abefhkmnptuvxBCEHPT] [+o option-name] [arg ...]
Without options, the name and value of each shell variable are displayed in a format that can be reused as input for setting or resetting the cur‐
rently-set variables. Read-only variables cannot be reset. In posix mode, only shell variables are listed. The output is sorted according to the
current locale. When options are specified, they set or unset shell attributes. Any arguments remaining after option processing are treated as
values for the positional parameters and are assigned, in order, to $1, $2, ... $n. Options, if specified, have the following meanings:
-a Automatically mark variables and functions which are modified or created for export to the environment of subsequent commands.
-b Report the status of terminated background jobs immediately, rather than before the next primary prompt. This is effective only when job
control is enabled.
-e Exit immediately if a pipeline (which may consist of a single simple command), a subshell command enclosed in parentheses, or one of the
commands executed as part of a command list enclosed by braces (see SHELL GRAMMAR above) exits with a non-zero status. The shell does not
exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test following the if
or elif reserved words, part of any command executed in a && or || list except the command following the final && or ||, any command in a
pipeline but the last, or if the command's return value is being inverted with !. A trap on ERR, if set, is executed before the shell
exits. This option applies to the shell environment and each subshell environment separately (see COMMAND EXECUTION ENVIRONMENT above), and
may cause subshells to exit before executing all the commands in the subshell.
-f Disable pathname expansion.
-h Remember the location of commands as they are looked up for execution. This is enabled by default.
-k All arguments in the form of assignment statements are placed in the environment for a command, not just those that precede the command
name.
-m Monitor mode. Job control is enabled. This option is on by default for interactive shells on systems that support it (see JOB CONTROL
above). Background processes run in a separate process group and a line containing their exit status is printed upon their completion.
-n Read commands but do not execute them. This may be used to check a shell script for syntax errors. This is ignored by interactive shells.
-x After expanding each simple command, for command, case command, select command, or arithmetic for command, display the expanded value of
PS4, followed by the command and its expanded arguments or associated word list.
当使用set -f时,通配符在匹配文件名时就不work了,
[superman@localhost perl]$ set -f; set -x; find . -name *.pl; set +x
+ find . -name '*.pl'
./fun.pl
./json_parser.pl
./login_client.pl
./test_perl.pl
./test_perl_withoutM.pl
./threads/join.pl
./threads/test.pl
./threads/thread.pl
./xmlParser.pl
+ set +x
由此可见,使用
set -f的作用与将通配符转义的效果是一样。另外也可以用单引号括起来通配符,以防止其转义。
还有
>find . -name \*.java -print0
./objectConvert.java./webservice/SingleFileHTTPServer.java./webservice/input.java./StringMain.java./staticBlock.java
这个-print0和-print又有什么区别呢?
>find . -name \*.java -print
./objectConvert.java
./webservice/SingleFileHTTPServer.java
./webservice/input.java
./StringMain.java
./staticBlock.java
-print0是输出以\0结尾,而不是用newline符号\n.
>echo -e "\0aa"
aa
>echo -e "\naa"
aa
>echo "\0aa"
\0aa
-print0
True; print the full file name on the standard output, followed
by a null character (instead of the newline character that
-print uses). This allows file names that contain newlines or
other types of white space to be correctly interpreted by pro‐
grams that process the find output. This option corresponds to
the -0 option of xargs.
例如:
>find . -name \*.java -print0 | xargs ls
xargs: Warning: a NUL character occurred in the input. It cannot be passed through in the argument list. Did you mean to use the --null option?
./objectConvert.java
>find . -name \*.java -print0 | xargs -0 ls
./objectConvert.java ./staticBlock.java ./StringMain.java ./webservice/input.java ./webservice/SingleFileHTTPServer.java
>find . -name \*.java -print0 | xargs -0 ls -l
-rw-r--r-- 1 user users 553 Aug 30 13:23 ./objectConvert.java
-rw-r--r-- 1 user users 1061 Aug 27 09:10 ./staticBlock.java
-rw-r--r-- 1 user users 595 Sep 13 02:41 ./StringMain.java
-rw-r--r-- 1 user users 4059 Aug 28 02:15 ./webservice/input.java
-rw-r--r-- 1 user users 4059 Aug 28 02:12 ./webservice/SingleFileHTTPServer.java