4

So, I'm trying to make myself a Python script which goes through the selected Music folder and tells the user if specific album doesn't have an album cover. It basically goes through all the files and checks if file[-4:] in (".jpg",".bmp",".png"), if true, it found a picture file. Just to make it clear, the structure of my folders is:

  • Music folder
    • Arctic Monkeys
      • Humbug (2009)
      • Suck it and see (2011)
    • Morphine
      • Cure For Pain (1993)

.. and so on. I'm testing the script to find if there's a missing cover in my Arctic Monkeys directory, and my script goes through the "Humbug (2009)" folder and finds AlbumArtSmall.jpg which doesn't show up in the command prompt so I tried "Show hidden files/folders" and still nothing. However, the files show up once I uncheck "Hide protected operating system files", so that's kinda weird.

My question is - how do I tell Python to skip searching the hidden/protected files? I checked out the How to ignore hidden files using os.listdir()? but the solution I found there only works for files starting with ".", and that's not what I need.

Cheers!


Edit - so here's the code:

import os

def findCover(path, band, album):
    print os.path.join(path, band, album)
    coverFound = False

    for mFile in os.listdir(os.path.join(path, band, album)):
        if mFile[-4:] in (".jpg",".bmp",".png"):
            print "Cover file found - %s." % mFile
            coverFound = True
            return coverFound

musicFolder = "E:\Music"   #for example
noCovers = []

for band in os.listdir(musicFolder):    #iterate over bands inside the music folder
    if band[0:] == "Arctic Monkeys":    #only Arctic Monkeys
        print band
        bandFolder = os.path.join(musicFolder, band)
        for album in os.listdir(bandFolder):
            if os.path.isdir(os.path.join(bandFolder,album)):
                if findCover(musicFolder, band, album): #if cover found
                    pass                                #do nothing
                else:
                    print "Cover not found"
                    noCovers.append(band+" - "+album)   #append to list
            else:                       #if bandFolder is not actually a folder
                pass
        print ""
Community
  • 1
  • 1
E. Normous
  • 543
  • 2
  • 7
  • 14
  • A proper answer will depend on how you're walking through your directory, but nevertheless, have you thought about checking the file mode with [os.stat](http://docs.python.org/library/os.html#os.stat)? – Pierre GM Aug 26 '12 at 13:32
  • I've added the code, hope that helps. Anyway, I tried the `os.stat("Folder.jpg")`, this is what I get: `nt.stat_result(st_mode=33206, st_ino=0L, st_dev=0, st_nlink=0, st_uid=0, st_gid=0, st_size=34820L, st_atime=1315277420L, st_mtime=1259528972L, st_ctime=1259525728L)`. I'm not really sure which of the values tells me the file is "protected" or "hidden" for that matter. Hm. – E. Normous Aug 26 '12 at 15:52
  • Doing the os.stat() on an .mp3 file which is visible returns pretty much the same values: `nt.stat_result(st_mode=33206, st_ino=0L, st_dev=0, st_nlink=0, st_uid=0, st_gid=0, st_size=8379620L, st_atime=1315277422L, st_mtime=1259529036L, st_ctime=1250607460L)`. – E. Normous Aug 26 '12 at 15:57
  • I might be wrong here, but I think os.stat has no concept of the custom filtering mechanism that windows uses to catalog protected system files. – jdi Aug 26 '12 at 16:20
  • @TankorSmash: the link was already given in the first comment, but `explicit is better than implicit`, eh ? – Pierre GM Aug 26 '12 at 16:22
  • @E. Normous : you should only need the `.st_mode` attribute: `os.stat(yourfile).st_mode`. Googling a `file mode 33206` could tell you it's a protected/hidden file. Knowing that, you could check for a not-hidden, not-protected file to get `33188`, for example. Now you would just have to test on whether `os.stat(yourfile).st_mode == 33206` or not... – Pierre GM Aug 26 '12 at 16:29
  • @PierreGM Heh, I guess it is. Still I'll remove my redundant comment. – TankorSmash Aug 26 '12 at 16:37
  • @PierreGM: I did the `os.stat(file).st_mode` for both hidden and not-hidden files, and it returns `33206` for both of them, unfortunately =/ – E. Normous Aug 26 '12 at 16:46
  • @E.Normous Made a significant edit to my answer that checks whether or not a file is hidden or not – TankorSmash Aug 26 '12 at 17:01

1 Answers1

1

You can use with the pywin32 module, and manually test for FILE_ATTRIBUTE_HIDDEN or any number of attributes

FILE_ATTRIBUTE_ARCHIVE              = 32
FILE_ATTRIBUTE_ATOMIC_WRITE         = 512
FILE_ATTRIBUTE_COMPRESSED           = 2048
FILE_ATTRIBUTE_DEVICE               = 64
FILE_ATTRIBUTE_DIRECTORY            = 16
FILE_ATTRIBUTE_ENCRYPTED            = 16384
FILE_ATTRIBUTE_HIDDEN               = 2
FILE_ATTRIBUTE_NORMAL               = 128
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED  = 8192
FILE_ATTRIBUTE_OFFLINE              = 4096
FILE_ATTRIBUTE_READONLY             = 1
FILE_ATTRIBUTE_REPARSE_POINT        = 1024
FILE_ATTRIBUTE_SPARSE_FILE          = 512
FILE_ATTRIBUTE_SYSTEM               = 4
FILE_ATTRIBUTE_TEMPORARY            = 256
FILE_ATTRIBUTE_VIRTUAL              = 65536
FILE_ATTRIBUTE_XACTION_WRITE        = 1024

like so:

import win32api, win32con

#test for a certain type of attribute
attribute = win32api.GetFileAttributes(filepath)
#The file attributes are bitflags, so you want to see if a given flag is 1.
# (AKA if it can fit inside the binary number or not) 
# 38 in binary is  100110 which means that 2, 4 and 32 are 'enabled', so we're checking for that
## Thanks to Nneoneo
if attribute & (win32con.FILE_ATTRIBUTE_HIDDEN | win32con.FILE_ATTRIBUTE_SYSTEM):
  raise Exception("hidden file") #or whatever

#or alter them
win32api.SetFileAttributes(filepath, win32con.FILE_ATTRIBUTE_NORMAL) #or FILE_ATTRIBUTE_HIDDEN

After you alter a file, take a look in the folder, it won't be hidden anymore.

Found this information here and here: Checking file attributes in python


Alternatively, you can try to use the os.stat function, whose docs here and then use the stat module to further understand what you're looking at.

Found these relevant questions. (python) meaning of st_mode and How can I get a file's permission mask?

Community
  • 1
  • 1
TankorSmash
  • 12,186
  • 6
  • 68
  • 106
  • Are you positive this reflects what windows considers "protected system files"? I have a feeling that is a custom mechanism. – jdi Aug 26 '12 at 16:21
  • @jdi Made a change to check for system hidden files. Hopefully that works for him. I'm not actually sure what the proper name for `protected system files` are... possibly `FILE_ATTRIBUTE_SYSTEM` but I haven't tested it out. – TankorSmash Aug 26 '12 at 16:54
  • @TankorSmash, man, thanks for all the help, I appreciate it =) At first it didn't work the way it's supposed to. For example, when I ran your code the `if` condition was `False` because the values were not equal - `attribute = 38` and `win32con.FILE_ATTRIBUTE_HIDDEN = 2`. So, `win32api.GetFileAttributes(HiddenFile)` returns `38`, while visible files have `32` for a value. Changed the if condition to `if attribute == 38` and that's it. Played around with `win32api.SetFileAttributes` and that works as it's supposed to. Very nice man, thanks for the help, you rock! – E. Normous Aug 26 '12 at 17:48
  • Happy to help! I wonder if `38` means that it's `SYSTEM = 2`, `HIDDEN = 4` and `ARCHIVE = 32`, like some sort of binary encoding or something. – TankorSmash Aug 26 '12 at 18:48
  • So, actually, you want `if attribute & win32con.FILE_ATTRIBUTE_HIDDEN`, since the attributes are bitflags. Also, when you modify the attributes, you must use bit operations to change only the selected attribute, or you risk overwriting some flags you didn't intend to. – nneonneo Aug 26 '12 at 18:49
  • @nneonneo Ah, bitflag is probably the name I'm looking for. – TankorSmash Aug 26 '12 at 18:50
  • Further to this: `HIDDEN` corresponds to 'show hidden files and folders', while `SYSTEM` corresponds to 'protected operating system files'. If you want to skip both, the test should be `if attribute & (win32con.FILE_ATTRIBUTE_HIDDEN | win32con.FILE_ATTRIBUTE_SYSTEM)`. – nneonneo Aug 26 '12 at 18:53
  • Anyway, I'd recommend adjusting your answer to use a flag test (`&`), and to use `attributes & ~win32con.FILE_ATTRIBUTE_HIDDEN` in the `SetFileAttributes` call (instead of just `win32con.FILE_ATTRIBUTE_NORMAL`). – nneonneo Aug 26 '12 at 18:56