[Python] 解決 glob.glob() 遇到檔名中有 [ 的問題

[Python] 解決 glob.glob() 遇到檔名中有 [ 的問題

Python 的 glob.glob() 函式真是出乎我的意料之外,有不少的隱藏秘笈…

上一次是遇到 不會傳回 Linux 上的隱藏檔 的問題,

今天又遇到了一個怪異狀況,

有個目錄名叫 test[1],目錄下有好幾個檔案,

但是用下列的程式卻傳回了空的 list: 

glob.glob("test[1]/*")

 

百思不得其解,後來看了 python manual

原來 glob() 會把 *?[] 視為特殊字元…

*? 很容易理解,[] 的話則是代表要符合中括號中的任一字元,

因此上面的程式事實上只會符合到 test1/*,自然是沒有東西了…

 

瞄了一下 python 2.6 中關於 glob() 的原始碼,

為了解決上述的問題 (加上之前隱藏檔的問題),

決定複製原本的 glob() 函式,修改成我需要的版本,也就是:

  1. 要列出隱藏檔

  2. 要把 [ 當作普通字元,不要作特殊的 regular expression 用途 

下面的 list_matched_filenames() 和 ilist_matched_filenames() 就分別對應到原本的 glob() 和 iglob(),

有興趣的人可以拿來跟 python 2.6 中的 glob() 比較看看囉~~

def list_matched_filenames(pathname, treat_left_bracket_as_normal_char=True):
"""
    This function comes from python 2.6 glob.glob().
    We modify it to allow hidden files and treat "[" as normal character.
    """
return list(ilist_matched_filenames(pathname, treat_left_bracket_as_normal_char))
def ilist_matched_filenames(pathname, treat_left_bracket_as_normal_char=True):
"""
    This function comes from python 2.6 glob.iglob().
    We modify it to allow hidden files and treat "[" as normal character.
    """
def _glob1(dirname, pattern):
"""
        This function comes from python 2.6 glob.glob1().
        We modify it to allow hidden files and treat "[" as normal character.
        """
if not dirname:
dirname = os.curdir
if isinstance(pattern, unicode) and not isinstance(dirname, unicode):
dirname = unicode(dirname, sys.getfilesystemencoding() or
sys.getdefaultencoding())
try:
names = os.listdir(dirname)
except os.error:
return []
import fnmatch
return fnmatch.filter(names, pattern if not treat_left_bracket_as_normal_char else pattern.replace("[", "[[]"))
import glob
if not glob.has_magic(pathname):
if os.path.lexists(pathname):
yield pathname
return
dirname, basename = os.path.split(pathname)
if not dirname:
for name in _glob1(os.curdir, basename):
yield name
return
if glob.has_magic(dirname):
dirs = ilist_matched_filenames(dirname, treat_left_bracket_as_normal_char)
else:
dirs = [dirname]
if glob.has_magic(basename):
glob_in_dir = _glob1
else:
glob_in_dir = glob.glob0
for dirname in dirs:
for name in glob_in_dir(dirname, basename):
yield os.path.join(dirname, name)

 

 

(本頁面已被瀏覽過 1,000 次)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料