如何在 Python 中检查文件夹的“隐藏”属性?

Posted

技术标签:

【中文标题】如何在 Python 中检查文件夹的“隐藏”属性?【英文标题】:How do I Check a Folder's 'hidden' Attribute in Python? 【发布时间】:2022-01-24 04:09:27 【问题描述】:

我正在开发一个加载/保存模块(用 Python 编写的 GUI),该模块将与未来的程序一起使用并导入到未来的程序中。我的操作系统是 Windows 10。我遇到的问题是我的 get_folders() 方法正在获取所有文件夹名称,包括我宁愿忽略的文件夹名称,例如系统文件夹和隐藏文件夹(最好在 c 驱动器上看到)。

我有一个使用硬编码排除列表的方法。但这仅适用于列表中已经存在的文件夹,不适用于我的向导将来可能遇到的隐藏文件夹。我想排除设置了“隐藏”属性的 ALL 文件夹。我想避免需要安装新库的方法,每当我擦除系统时都必须重新安装这些库。此外,如果解决方案不是特定于 Windows 的,但也适用于 Windows 10,那就更好了。

我已经在 SO 和网络上搜索了答案,但没有找到答案。我找到的最接近的答案包含在此线程的答案 #4 中:Check for a folder, then create a hidden folder in Python,它显示了如何在创建新目录时设置隐藏属性,而不是如何读取现有目录的隐藏属性。

这是我的问题:有没有人知道一种方法来检查文件夹的“隐藏”属性是否已设置,使用本机 python、pygame 或 os。命令?或者,如果没有原生答案,我会接受从库中导入的方法来实现我的目标。

以下程序演示了我的 get_folders() 方法,并显示了手头的问题:

# Written for Windows 10
import os
import win32gui

CLS = lambda :os.system('cls||echo -e \\\\033c') # Clear-Command-Console function

def get_folders(path = -1, exclude_list = -1):
    
    if path == -1: path = os.getcwd()    
    if exclude_list == -1: exclude_list = ["Config.Msi","Documents and Settings","System Volume Information","Recovery","ProgramData"]
    
    dir_list = [entry.name for entry in os.scandir(path) if entry.is_dir()] if exclude_list == [] else\
     [entry.name for entry in os.scandir(path) if entry.is_dir() and '$' not in entry.name and entry.name not in exclude_list]
    
    return dir_list

def main():
    
    HWND = win32gui.GetForegroundWindow()                 # Get Command Console Handle.
    win32gui.MoveWindow(HWND,100,50,650,750,False) # Size and Position Command Console.
    CLS()  # Clear Console Screen.
    
    print(''.join(['\n','Folder Names'.center(50),'\n ',('-'*50).center(50)]))
    
    # Example 1: Current Working Directory        
    dirs = get_folders()  # Get folder names in current directory (uses exclude list.)
    for elm in dirs:print(' ',elm)  # Show the folder names.
    print('','-'*50)

    # Examle 2: C Drive, All Folders Included
    dirs = get_folders('c:\\', exclude_list = []) # Get a list of folders in the root c: drive, nothing excluded.
    for elm in dirs: print(' ',elm) # Show the fiolder names
    print('','-'*50)
    
    # Example 3: C Drive, Excluded Folder List Work-Around
    dirs = get_folders('c:\\')      # Get a list of folders in the root c: drive, excluding sytem dirs those named in the exclude_list.
    for elm in dirs:print(' ',elm)   # Show the folder names.

    print("\n Question: Is there a way to identify folders that have the 'hidden' attribute\n\t set to True, rather than using a hard-coded exclusion list?",end='\n\n' )

# ==========================
if __name__ == "__main__": 
    main()
    input(' Press [Enter] to Quit: ')
    CLS()

【问题讨论】:

我认为answer 会帮助你 亚历山大,这正是我所需要的。答案充满了精彩的技巧和参考资料,在很长一段时间内,它将成为我学习和灵感的源泉。谢谢! 【参考方案1】:

这是我修改后的 get_folders() 方法,感谢 Alexander。

# Written for Windows 10
# key portions of this code borrowed from:
# https://***.com/questions/40367961/how-to-read-or-write-the-a-s-h-r-i-file-attributes-on-windows-using-python-and-c/40372658#40372658
# with thanks to Alexander Goryushkin.

import os
from os import scandir, stat
from stat import (
    FILE_ATTRIBUTE_ARCHIVE as A,
    FILE_ATTRIBUTE_SYSTEM as S,
    FILE_ATTRIBUTE_HIDDEN as H,
    FILE_ATTRIBUTE_READONLY as R,
    FILE_ATTRIBUTE_NOT_CONTENT_INDEXED as I
    )
from ctypes import WinDLL, WinError, get_last_error
import win32gui

CLS = lambda :os.system('cls||echo -e \\\\033c') # Clear-Command-Console function

def read_or_write_attribs(kernel32, entry,  a=None, s=None, h=None, r=None, i=None,  update=False):

    # Get the file attributes as an integer.
    if not update: attrs = entry.stat(follow_symlinks=False).st_file_attributes# Fast because we access the stats from the entry
    else:
        # Notice that this will raise a "WinError: Access denied" on some entries,
        # for example C:\System Volume Information\
        attrs = stat(entry.path, follow_symlinks=False).st_file_attributes
        # A bit slower because we re-read the stats from the file path.

    # Construct the new attributes
    newattrs = attrs
    def setattrib(attr, value):
        nonlocal newattrs
        # Use '0:032b'.format(number) to understand what this does.
        if value is True: newattrs = newattrs | attr
        elif value is False: 
              newattrs = newattrs & ~attr
              setattrib(A, a)
              setattrib(S, s)
              setattrib(H, h)
              setattrib(R, r)
              setattrib(I, i if i is None else not i)  # Because this attribute is True when the file is _not_ indexed

    # Optional add more attributes here. 
    # See https://docs.python.org/3/library/stat.html#stat.FILE_ATTRIBUTE_ARCHIVE

    # Write the new attributes if they changed
    if newattrs != attrs:
        if not kernel32.SetFileAttributesW(entry.path, newattrs):
            raise WinError(get_last_error())

    # Return an info tuple consisting of bools
    return ( bool(newattrs & A), 
                   bool(newattrs & S), 
                   bool(newattrs & H), 
                   bool(newattrs & R), 
                   not bool(newattrs & I) )# Because this attribute is true when the file is _not_ indexed)

    # Get the file attributes as an integer.
    if not update:
        # Fast because we access the stats from the entry
        attrs = entry.stat(follow_symlinks=False).st_file_attributes
    else:
        # A bit slower because we re-read the stats from the file path.
        # Notice that this will raise a "WinError: Access denied" on some entries,
        # for example C:\System Volume Information\
        attrs = stat(entry.path, follow_symlinks=False).st_file_attributes
    return dir_list

def get_folders(path = -1, show_hidden = False):
        
    if path == -1: path = os.getcwd()    
    dir_list = []
    kernel32 = WinDLL('kernel32', use_last_error=True)
    for entry in scandir(path):
        a,s,hidden,r,i = read_or_write_attribs(kernel32,entry)
        
        if entry.is_dir() and (show_hidden or not hidden): dir_list.append(entry.name)
    return dir_list
    
def main():

    HWND = win32gui.GetForegroundWindow()                 # Get Command Console Handle.
    win32gui.MoveWindow(HWND,100,50,650,750,False) # Size and Position Command Console.
    CLS()  # Clear Console Screen.

    line_len = 36

    # Example 1: C Drive, Exclude Hidden Folders
    print(''.join(['\n','All Folders Not Hidden:'.center(line_len),'\n ',('-'*line_len).center(line_len)]))        
    dirs = get_folders('c:\\')  # Get a list of folders on the c: drive, exclude hidden.
    for elm in dirs:print(' ',elm)  # Show the folder names.
    print('','='*line_len)

    # Examle 2: C Drive, Include Hidden Folders
    print("  All Folders Including Hidden\n "+"-"*line_len)
    dirs = get_folders('c:\\', show_hidden = True) # Get a list of folders on the c: drive, including hidden.
    for elm in dirs: print(' ',elm) # Show the fiolder names
    print('','-'*line_len)
# ==========================
if __name__ == "__main__": 
    main()
    input(' Press [Enter] to Quit: ')
    CLS()

【讨论】:

以上是关于如何在 Python 中检查文件夹的“隐藏”属性?的主要内容,如果未能解决你的问题,请参考以下文章

在 IDE 对象检查器中动态显示/隐藏属性?

在python中检查文件属性

检查文件或目录是不是隐藏

如何在解析之前检查 XML 中是不是存在属性和标签?

Spring Boot如何在属性文件中隐藏密码

约束/自动布局栏隐藏,Xcode 6