Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

In python, how can I identify a file that is a "window system file". From the command line I can do this with the following command:

ATTRIB "c:file_path_name.txt"

If the return has the "S" character, then it's a windows system file. I cannot figure out the equivilant in python. A few example of similar queries look like this:

Is a file writeable?

import os

filePath = r'c:	estfile.txt'

if os.access(filePath, os.W_OK):
   print 'writable'
else:
   print 'not writable'

another way...

import os
import stat

filePath = r'c:	estfile.txt'

attr = os.stat(filePath)[0]
if not attr & stat.S_IWRITE:
   print 'not writable'
else:
   print 'writable'

But I can't find a function or enum to identify a windows system file. Hopefully there's a built in way to do this. I'd prefer not to have to use win32com or another external module.

The reason I want to do this is because I am using os.walk to copy files from one drive to another. If there was a way to walk the directory tree while ignoring system files that may work too.

Thanks for reading.



Here's the solutions I came up with based on the answer:

Using win32api:

import win32api
import win32con

filePath = r'c:	est_file_path.txt'

if not win32api.GetFileAttributes(filePath) & win32con.FILE_ATTRIBUTE_SYSTEM:
   print filePath, 'is not a windows system file'
else:
   print filePath, 'is a windows system file'

and using ctypes:

import ctypes
import ctypes.wintypes as types

# From pywin32
FILE_ATTRIBUTE_SYSTEM = 0x4

kernel32dll = ctypes.windll.kernel32


class WIN32_FILE_ATTRIBUTE_DATA(ctypes.Structure):
   _fields_ = [("dwFileAttributes", types.DWORD),
               ("ftCreationTime", types.FILETIME),
               ("ftLastAccessTime", types.FILETIME),
               ("ftLastWriteTime", types.FILETIME),
               ("nFileSizeHigh", types.DWORD),
               ("nFileSizeLow", types.DWORD)]

def isWindowsSystemFile(pFilepath):
   GetFileExInfoStandard = 0

   GetFileAttributesEx = kernel32dll.GetFileAttributesExA
   GetFileAttributesEx.restype = ctypes.c_int
   # I can't figure out the correct args here
   #GetFileAttributesEx.argtypes = [ctypes.c_char, ctypes.c_int, WIN32_FILE_ATTRIBUTE_DATA]

   wfad = WIN32_FILE_ATTRIBUTE_DATA()
   GetFileAttributesEx(pFilepath, GetFileExInfoStandard, ctypes.byref(wfad))

   return wfad.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM

filePath = r'c:	est_file_path.txt'

if not isWindowsSystemFile(filePath):
   print filePath, 'is not a windows system file'
else:
   print filePath, 'is a windows system file'

I wonder if pasting the constant "FILE_ATTRIBUTE_SYSTEM" in my code is legit, or can I get its value using ctypes as well?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
139 views
Welcome To Ask or Share your Answers For Others

1 Answer

But I can't find a function or enum to identify a windows system file. Hopefully there's a built in way to do this.

There is no such thing. Python's file abstraction doesn't have any notion of "system file", so it doesn't give you any way to get it. Also, Python's stat is a very thin wrapper around the stat or _stat functions in Microsoft's C runtime library, which doesn't have any notion of "system file". The reason for this is that both Python files and Microsoft's C library are both designed to be "pretty much like POSIX".

Of course Windows also has a completely different abstraction for files. But this one isn't exposed by the open, stat, etc. functions; rather, there's a completely parallel set of functions like CreateFile, GetFileAttributes, etc. And you have to call those if you want that information.

I'd prefer not to have to use win32com or another external module.

Well, you don't need win32com, because this is just Windows API, not COM.

But win32api is the easiest way to do it. It provides a nice wrapper around GetFileAttributesEx, which is the function you want to call.

If you don't want to use an external module, you can always call Windows API functions via ctypes instead. Or use subprocess to run command-line tools (like ATTRIB—or, if you prefer, like DIR /S /A-S to let Windows do the recursive-walk-skipping-system-files bit for you…).

The ctypes docs show how to call Windows API functions, but it's a little tricky the first time.

First you need to go to the MSDN page to find out what DLL you need to load (kernel32), and whether your function has separate A and W variants (it does), and what values to pass for any constants (you have to follow a link to another page, and know how C enums works, to find out that GetFileExInfoStandard is 0), and then you need to figure out how to define any structs necessary. In this case, something like this:

from ctypes import *
kernel = windll.kernel32

GetFileExInfoStandard = 0

GetFileAttributesEx = kernel.GetFileAttributesEx
GetFileAttributesEx.restype = c_int
GetFileAttributesEx.argypes = # ...

If you really want to avoid using win32api, you can do the work to finish the ctypes wrapper yourself. Personally, I'd use win32api.


Meanwhile:

The reason I want to do this is because I am using os.walk to copy files from one drive to another. If there was a way to walk the directory tree while ignoring system files that may work too.

For that case, especially given your complaint that checking each file was too slow, you probably don't want to use os.walk either. Instead, use FindFirstFileEx, and do the recursion manually. You can distinguish files and directories without having to stat (or GetFileAttributesEx) each file (which os.walk does under the covers), you can filter out system files directly inside the find function instead of having to stat each file, etc.

Again, the options are the same: use win32api if you want it to be easy, use ctypes otherwise.

But in this case, I'd take a look at Ben Hoyt's betterwalk, because he's already done 99% of the ctypes-wrapping, and 95% of the rest of the code, that you want.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...