File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -40,6 +40,17 @@ For example, ``'[?]'`` matches the character ``'?'``.
4040 without actually storing them all simultaneously.
4141
4242
43+ .. function :: escape(pathname)
44+
45+ Escape all special characters (``'?' ``, ``'*' `` and ``'[' ``).
46+ This is useful if you want to match an arbitrary literal string that may
47+ have special characters in it. Special characters in drive/UNC
48+ sharepoints are not escaped, e.g. on Windows
49+ ``escape('//?/c:/Quo vadis?.txt') `` returns ``'//?/c:/Quo vadis[?].txt' ``.
50+
51+ .. versionadded :: 3.4
52+
53+
4354For example, consider a directory containing only the following files:
4455:file: `1.gif `, :file: `2.txt `, and :file: `card.gif `. :func: `glob ` will produce
4556the following results. Notice how any leading components of the path are
Original file line number Diff line number Diff line change @@ -79,8 +79,8 @@ def glob0(dirname, basename):
7979 return []
8080
8181
82- magic_check = re .compile ('[*?[]' )
83- magic_check_bytes = re .compile (b'[*?[]' )
82+ magic_check = re .compile ('( [*?[]) ' )
83+ magic_check_bytes = re .compile (b'( [*?[]) ' )
8484
8585def has_magic (s ):
8686 if isinstance (s , bytes ):
@@ -91,3 +91,15 @@ def has_magic(s):
9191
9292def _ishidden (path ):
9393 return path [0 ] in ('.' , b'.' [0 ])
94+
95+ def escape (pathname ):
96+ """Escape all special characters.
97+ """
98+ # Escaping is done by wrapping any of "*?[" between square brackets.
99+ # Metacharacters do not work in the drive part and shouldn't be escaped.
100+ drive , pathname = os .path .splitdrive (pathname )
101+ if isinstance (pathname , bytes ):
102+ pathname = magic_check_bytes .sub (br'[\1]' , pathname )
103+ else :
104+ pathname = magic_check .sub (r'[\1]' , pathname )
105+ return drive + pathname
Original file line number Diff line number Diff line change @@ -169,6 +169,28 @@ def test_glob_magic_in_drive(self):
169169 eq (glob .glob ('\\ \\ *\\ *\\ ' ), [])
170170 eq (glob .glob (b'\\ \\ *\\ *\\ ' ), [])
171171
172+ def check_escape (self , arg , expected ):
173+ self .assertEqual (glob .escape (arg ), expected )
174+ self .assertEqual (glob .escape (os .fsencode (arg )), os .fsencode (expected ))
175+
176+ def test_escape (self ):
177+ check = self .check_escape
178+ check ('abc' , 'abc' )
179+ check ('[' , '[[]' )
180+ check ('?' , '[?]' )
181+ check ('*' , '[*]' )
182+ check ('[[_/*?*/_]]' , '[[][[]_/[*][?][*]/_]]' )
183+ check ('/[[_/*?*/_]]/' , '/[[][[]_/[*][?][*]/_]]/' )
184+
185+ @unittest .skipUnless (sys .platform == "win32" , "Win32 specific test" )
186+ def test_escape_windows (self ):
187+ check = self .check_escape
188+ check ('?:?' , '?:[?]' )
189+ check ('*:*' , '*:[*]' )
190+ check (r'\\?\c:\?' , r'\\?\c:\[?]' )
191+ check (r'\\*\*\*' , r'\\*\*\[*]' )
192+ check ('//?/c:/?' , '//?/c:/[?]' )
193+ check ('//*/*/*' , '//*/*/[*]' )
172194
173195def test_main ():
174196 run_unittest (GlobTests )
Original file line number Diff line number Diff line change @@ -50,6 +50,8 @@ Core and Builtins
5050Library
5151-------
5252
53+ - Issue #8402: Added the escape() function to the glob module.
54+
5355- Issue #17618: Add Base85 and Ascii85 encoding/decoding to the base64 module.
5456
5557- Issue #19634: time.strftime("%y") now raises a ValueError on AIX when given a
You can’t perform that action at this time.
0 commit comments