shopt nullglob, failglob, extglob, globstar用法

shopt nullglob, failglob, extglob, globstar的用法


#!/usr/bin/env bash

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

shopt -s extglob
shopt -s nullglob

for f in $PIG_HOME/lib/*.jar; do

JYTHON_JAR=`echo ${PIG_HOME}/lib/jython*.jar`

for f in $PIG_HOME/share/pig/lib/*.jar; do

# restore ordinary behaviour
unset IFS

shopt -u nullglob
shopt -u extglob 


   man shopt
       -s enable
       -u disable

           If set, the extended pattern matching features described above under Pathname Expansion are enabled.
           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的。


              If set, patterns which fail to match filenames during pathname expansion result in an expansion error.


>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'


     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后,**递归的匹配了所有文件和目录, 如果**后面跟着/(即是**/),则只匹配目录。

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/
可以看到打开globstar后,**递归的匹配了所有文件和目录, 如果**后面跟着/(即是**/),则只匹配目录。
问题来了,如果递归显示以.txt结尾到文件,是不是**.txt? 非也,来看看
igi@gentoo ~/test $ shopt -s globstar
igi@gentoo ~/test $ shopt globstar
globstar        on
igi@gentoo ~/test $ find . -name '*.txt'
igi@gentoo ~/test $ echo **.txt
igi@gentoo ~/test $ echo **/*.txt
a.txt c/2.txt c/3.txt c/4.txt

看到了吧,**.txt是无法递归的,而**/*.txt就可以了,同理, foo**这样也不行,**/foo*这样到才可以。
>bash -version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)



>shopt failglob
failglob        on
>let num=3*3
-bash: no match: num=3*3

即便是touch 3*3的文件(3\*3),这个算术运算也不成功。


>shopt -u failglob
>shopt  failglob
failglob        off
>let num=3*3
>echo $num

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

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

>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:

                     Matches zero or one occurrence of the given patterns
                     Matches zero or more occurrences of the given patterns
                     Matches one or more occurrences of the given patterns
                     Matches one of the given patterns
                     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.