# shopt nullglob, failglob, extglob, globstar的用法

#!/usr/bin/env bash

# so that filenames w/ spaces are handled correctly in loops below
IFS=

shopt -s extglob
shopt -s nullglob

for f in $PIG_HOME/lib/*.jar; do CLASSPATH=${CLASSPATH}:$f; done JYTHON_JAR=echo${PIG_HOME}/lib/jython*.jar

for f in $PIG_HOME/share/pig/lib/*.jar; do CLASSPATH=${CLASSPATH}:$f; done ... # restore ordinary behaviour unset IFS ... shopt -u nullglob shopt -u extglob  其中nullglob的是什么意思呢？  man shopt -s enable -u disable extglob If set, the extended pattern matching features described above under Pathname Expansion are enabled. nullglob If set, bash allows patterns which match no files (see Pathname Expansion above) to expand to a null string, rather than themselves.  （通过 man bash 可以检索到对 “Pathname Expansion”的解释,其中陈述了extglob和nullglob对file 匹配时的用法） extglob 的另外用法： 对于nullglob来说, 就是在使用shell 的通配符*匹配文件时，如果没有匹配到任何文件时，那就会输出null string，而不是通配符字符本身。 为什么这么说呢？ >shopt nullglob nullglob off >mkdir tmp >cd tmp >for i in *; do echo "file:$i"; done
file: * 【这里把通配符*作为字符输出了】
>shopt -s nullglob
>shopt nullglob
nullglob        on
>for i in *; do echo "file: $i"; done 【null string，没有结果输出】  由此可以，在使用*来匹配一个文件时，如果该目录下并没有这个文件，这个通配符*就会作为一个字符，被当做一个文件来处理，这是很危险的。因此，在匹配file 时，nullglob是很有必要enable的。 当然也可以使用failglob，在没有匹配时报错。  failglob If set, patterns which fail to match filenames during pathname expansion result in an expansion error.  example: >shopt failglob failglob off >for i in *; do echo "file:$i"; done
file: *

>shopt -s failglob
>for i in *; do echo "file: $i"; done -bash: no match: *  另外， 单引号可以防止*号被替换。 [login@sonora resources]$ find ../ -name *.yidf
find: missing argument to -name'
[login@sonora resources]$find ../ -name '*.yidf' ../resources/slingshot.di.configservice.prod/image/runtime ../resources/slingshot.di.configservice.stage/image/runtime ../resources/common/pkg.yidf ../resources/slingshot.di.configservice.qe/image/runtime  #### globstar的例子  globstar If set, the pattern ** used in a pathname expansion context will match a files and zero or more directories and subdirectories. If the pattern is followed by a /, only directories and subdirectories match.  enable globstar后，**递归的匹配了所有文件和目录， 如果**后面跟着/(即是**/)，则只匹配目录。 默认情况下，globstar是关闭的，也就是**与*是一样的， igi@gentoo ~/test$ tree
.
├── a
│   ├── 1
│   ├── 2
│   ├── 3
│   ├── 4
│   └── 5
└── c
├── 2.txt
├── 3.txt
├── 4.txt
└── dir

3 directories, 8 files
igi@gentoo ~/test $shopt -s globstar igi@gentoo ~/test$ shopt globstar
globstar        on
igi@gentoo ~/test $echo * a c igi@gentoo ~/test$ echo **
a a/1 a/2 a/3 a/4 a/5 c c/2.txt c/3.txt c/4.txt c/dir
igi@gentoo ~/test $echo */ a/ c/ igi@gentoo ~/test$ echo **/
a/ c/ c/dir/

igi@gentoo ~/test $shopt -s globstar igi@gentoo ~/test$ shopt globstar
globstar        on
igi@gentoo ~/test $find . -name '*.txt' ./a.txt ./c/3.txt ./c/2.txt ./c/4.txt igi@gentoo ~/test$ echo **.txt
a.txt
igi@gentoo ~/test $echo **/*.txt a.txt c/2.txt c/3.txt c/4.txt 看到了吧，**.txt是无法递归的，而**/*.txt就可以了，同理， foo**这样也不行，**/foo*这样到才可以。 这个功能是bash4才有的哦，使用之前，先确认下你到bash版本。 >bash -version GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu) [以上参考http://www.igigo.net/archives/category/shell] 但是当enable了failglob之后，它就会把所有出现的*当做通配符，去匹配文件名了。例如： >shopt failglob failglob on >let num=3*3 -bash: no match: num=3*3  即便是touch 3*3的文件(3\*3)，这个算术运算也不成功。 但diable该选项之后，就ok了。 >shopt -u failglob >shopt failglob failglob off >let num=3*3 >echo$num
9


*号乘法运算, **冪运算

>let num=2**4
>echo \$num
16


>man bash

Pathname Expansion
After word splitting, unless the -f option has been set, bash scans each word for the characters *, ?, and [.  If one of  these  characters  appears,  then  the  word  is regarded  as  a  pattern,  and  replaced with an alphabetically sorted list of file names matching the pattern.

If no matching file names are found, and the shell option nullglob is not enabled, the word is left unchanged.

If the nullglob option is set, and no matches are found, the word is removed.

If the failglob shell option is  set,  and  no  matches are found, an error message is printed and the command is not executed.

If the shell option nocaseglob is enabled, the match is performed without regard to the case of alphabetic characters.

When a pattern is used for pathname expansion, the character  .'  '  at the start of a name or immediately following a slash must be  matched  explicitly,  unless the shell optiondotglobis set. When matching a pathname, the slash character must always be matched explicitly.  In other cases, the  `.' ' character is not treated specially.  See the description of shopt below under SHELL BUILTIN COMMANDS for a description of the nocaseglob, nullglob, failglob, and  dotglob  shell options.

Pattern Matching

Any character that appears in a pattern, other than the special pattern characters described below, matches itself.  The NUL character may not  occur  in  a  pattern.   A backslash  escapes  the  following  character; the escaping backslash is discarded when matching.  The special pattern characters must be quoted if they are to be matched literally.

The special pattern characters have the following meanings:

*      Matches any string, including the null string.  When the globstar shell option is enabled, and * is used in a pathname expansion context, two adjacent *s used as a single pattern will match all files and zero or more directories and subdirectoriesIf followed by a /, two adjacent *s will match only directories and subdirectories. */* 只会匹配目录了。

?      Matches any single character.

[...]  Matches any one of the enclosed characters.  A pair of characters separated by a hyphen denotes a range expression; any character  that  sorts  between  those  two characters, inclusive, using the current localeâs collating sequence and character set, is matched.  If the first character following the [ is a !  or a ^ then any
character not enclosed is matched.  The sorting order of characters in range expressions is determined by the current locale and the value of the LC_COLLATE  shell
variable,  if set.  A - may be matched by including it as the first or last character in the set.  A ] may be matched by including it as the first character in the set.

Within [ and ], character classes can be specified using the syntax [:class:], where class is one of the following classes defined in the POSIX standard:
alnum alpha ascii blank cntrl digit graph lower print punct space upper word xdigit
A character class matches any character belonging to that class.  The word character class matches letters, digits, and the character _.

Within [ and ], an equivalence class can be specified using the syntax [=c=], which matches all characters with the same collation weight (as defined by  the  cur-
rent locale) as the character c.

Within [ and ], the syntax [.symbol.] matches the collating symbol symbol.

If  the extglob shell option is enabled using the shopt builtin, several extended pattern matching operators are recognized. In the following description, a pattern-list is a list of one or more patterns separated by a |.  Composite patterns may be formed using one or more of the following sub-patterns:

?(pattern-list)
Matches zero or one occurrence of the given patterns
*(pattern-list)
Matches zero or more occurrences of the given patterns
+(pattern-list)
Matches one or more occurrences of the given patterns
@(pattern-list)
Matches one of the given patterns
!(pattern-list)
Matches anything except one of the given patterns

Quote Removal
After the preceding expansions, all unquoted occurrences of the characters \, ', and " that did not result from one of the above expansions are removed.