os.stat() distorts filenames that end with period (nt.stat())

ruck john.ruckstuhl at gmail.com
Fri Sep 7 01:54:17 EDT 2012


On Thursday, September 6, 2012 7:05:39 PM UTC-7, Terry Reedy wrote:
> On 9/6/2012 8:55 PM, ruck wrote:
> 
> > (This with Python 2.7.2 on Windows 7)
> 
> >
> 
> > os.stat() won't recognize a filename ending in period.
> 
> > It will ignore trailing periods.
> 
> > If you ask it about file 'goo...' it will report on file 'goo'
> 
> > And if 'goo' doesn't exist, os.stat will complain.
> 
> >
> 
> > create file goo, then
> 
> >
> 
> >      >>> os.stat('goo')
> 
> >      nt.stat_result(st_mode=33206, st_ino=0L, st_dev=0, st_nlink=0, st_uid=0, st_gid=0, st_size=0L, st_atime=1346978160L, st_mtime=1346978160L, st_ctime=1346978160L)
> 
> >      >>> os.stat('goo...')
> 
> >      nt.stat_result(st_mode=33206, st_ino=0L, st_dev=0, st_nlink=0, st_uid=0, st_gid=0, st_size=0L, st_atime=1346978160L, st_mtime=1346978160L, st_ctime=1346978160L)
> 
> >
> 
> > rename goo to "goo...", then,
> 
> >
> 
> >      >>> os.stat('goo...')
> 
> >
> 
> >      Traceback (most recent call last):
> 
> >        File "<pyshell#16>", line 1, in <module>
> 
> >          os.stat('goo...')
> 
> >      WindowsError: [Error 2] The system cannot find the file specified: 'goo...'
> 
> >
> 
> > Puzzling, to me at least.
> 
> > Any comments?
> 
> 
> 
> Windows have restrictions on filenames. The restrictions are not 
> 
> consistent in that some parts of Windows will let you make names that 
> 
> other parts do not recognize or regard as illegal. I ran into this some 
> 
> years ago and there may be a discussion on the tracker, but I have 
> 
> forgetten the details except that one of the 'parts' was Windows 
> 
> Explorer. This *might* be what you are running into.
> 
> 
> 
> -- 
> 
> Terry Jan Reedy

Summary:
I was complaining that
    >>> os.stat('goo...')

    Traceback (most recent call last):
      File "<pyshell#35>", line 1, in <module>
        os.stat('goo...')
    WindowsError: [Error 2] The system cannot find the file specified: 'goo...'

is actually looking for file 'goo' instead of the existing file 'goo...' -- that's why it errors.  
(Python 2.7.2, Windows 7)

Here's a workaround.
    >>> os.stat('\\\\?\\' + os.getcwd() + '\\' + 'goo...')
    nt.stat_result(st_mode=33206, st_ino=0L, st_dev=0, st_nlink=0, st_uid=0,
    st_gid=0, st_size=0L, st_atime=1346978160L, st_mtime=1346978160L, 
    st_ctime=1346978160L)

In other words, prefix the path (full path?) with \\?\ to disable the Windows API filename  interceptions.

Detail:
    "Naming Files, Paths, and Namespaces" ( http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx )
says

  Naming Conventions
  The following fundamental rules enable applications to 
  create and process valid names for files and directories, 
  regardless of the file system:
  
  * Do not end a file or directory name with a space or a 
  period. Although the underlying file system may support 
  such names, the Windows shell and user interface does not. 

In my case, the filesystem is NTFS and it does support filenames like 'goo...', and I'm not trying to use Windows shell or UI.  So how do I get to the underlying filesystem without interference?  Here (from the same reference)

  Namespaces
  There are two main categories of namespace conventions 
  used in the Windows APIs, commonly referred to as NT 
  namespaces and the Win32 namespaces.  ...

  Win32 File Namespaces
  The Win32 namespace prefixing and conventions are 
  summarized in this section and the following section, 
  with descriptions of how they are used. Note that these 
  examples are intended for use with the Windows API 
  functions and do not all necessarily work with Windows 
  shell applications such as Windows Explorer. For this 
  reason there is a wider range of possible paths than is 
  usually available from Windows shell applications, and 
  Windows applications that take advantage of this can be 
  developed using these namespace conventions.

  For file I/O, the "\\?\" prefix to a path string tells 
  the Windows APIs to disable all string parsing and to 
  send the string that follows it straight to the file 
  system. For example, if the file system supports large 
  paths and file names, you can exceed the MAX_PATH limits 
  that are otherwise enforced by the Windows APIs.

Thanks all for your comments and pointers.
John



More information about the Python-list mailing list