總結結果:
TL;博士
的OP經歷了意外的行爲由於bug 3.x版本的bash涉及某些擴展的全局模式,即與shopt -s extglob
有效。
然而,即使沒有錯誤,代碼不工作打算,因爲文件名匹配模式*file2*?(.gz)
實際上是相同的*file*
- 這將匹配文件與任何後綴,而不只是.gz
。
向含有file2
該要麼有沒有後綴可言,或,如果它們具有(至少)一個,具有.gz
一個[最後]後綴只有匹配的名字,使用*([^.])file2*([^.])?(*.gz)
(這也適用於bash 3.x)。請注意,與OP的模式一樣,此需要使用shopt -s extglob
激活擴展匹配。
的假設是OP的意圖如下:
比賽只包含名稱file2
[第一後綴之前,如果有的話]認爲要麼有沒有後綴或,如果它們[至少]一個,並且[後]後綴爲.gz
例如,匹配文件file2
file2-a
,some-file2
,file2.gz
,file2-a.gz
,file2.tar.gz
,但不file2.no
(因爲它有一個[最後]後綴不是 '廣州')。
雖然是一個bash 3.x的錯誤,影響的模式,如*?(...)
- 因爲*
比賽沒有很好的理由使用*?(...)
,因爲它是有效的和上面一樣*
, - 見下文任何字符序列,包括後綴。
下面的解決方案是而不是受該錯誤影響。
您不能使用*
匹配只有一個文件名(在[第一]後綴之前的部分)的根,因爲*
匹配任何字符串,是否一個後綴的一部分或沒有。
因此,擴展的水珠*([^.])
必須被使用,其包含任何字符除了.
(週期)的任何長度的字符串匹配。
此外,考慮到一個事實,即一個文件名可具有多個後綴,圖案的可選.gz
-matching部分應該是?(*.gz)
。
要放在一起:
注:shopt -s extglob
必須在工作命令的效果。
# Create test files; note the addition of "testfile2.tar.gz", which SHOULD
# match, and "testfile2.no", which should NOT match:
$ touch "testfile1" "testfile1.gz" "testfile2" "testfile2.gz" "testfile2.gz#id=142" "testfile2test" "testfile2test.gz" "testfile2.tar.gz" "testfile2.no"
$ ls -1 *([^.])file2*([^.])?(*.gz)
testfile2
testfile2.gz
testfile2.tar.gz
testfile2test
testfile2test.gz
# The same, using a variable:
$ file_mask=*([^.])file2*([^.]) # NO globbing here (no globbing in *assignments*).
$ file_mask+=?(*.gz) # Extend the pattern; still no globbing.
$ ls -1 $file_mask # Globbing happens here, due to unquoted use of the variable.
# Same output as before.
# Using a loop should work equally:
for f in *([^.])file2*([^.])?(*.gz); do echo "$f"; done
# Same output as before.
# Loop with a variable:
$ file_mask=*([^.])file2*([^.])
$ file_mask+=?(*.gz)
$ for f in $file_mask; do echo "$f"; done
# Same output as before.
暗紋擴展通配臭蟲在bash 3.x的:
注意,錯誤是無關是否被使用的變量。
我不知道該錯誤修復的版本是什麼,但它的不存在於4.3.30中。
總之,*?(...)
錯誤地表現爲好像*+(...)
已被指定。
換句話說:獨立簡單圖案*
隨後延長圖案?(...)
(匹配零或1...
實例)有效地表現得像*
接着+(...)
(匹配1以上...
實例)。
示範,在bash 3.2.57觀察(當前版本在OSX 10.10.2;在OP使用3.2.25):
$ touch f f.gz # create test files
$ ls -1 f?(.gz) # OK: finds files with basename root 'f', optionally suffixed with '.gz'
f
f.gz
# Now extend the glob with `*` after the basename root.
# This, in fact, is logically equivalent to `f*` and should
# match *all files starting with 'f'*.
$ ls -1 f*?(.gz)
f.gz
#^BUG: only matches the suffixed file.
'(GZ)'是嗎?告訴我們你的意圖... – 2015-03-03 12:22:33
這是一個擴展的glob。它意味着可以匹配一個'.gz'後綴。 – 2015-03-03 12:27:53
你在這裏遇到'failglob'的'不匹配'錯誤嗎? – 2015-03-03 12:29:33