14

In *nix I can simply add a . to a file to make it "hidden". There are also ways to make a file hidden in windows.

Is there a way in python to make a file hidden CROSS PLATFORM?

currently:

def write_hidden(file_name, data):
    file_name = '.' + file_name
    with open(file_name_, 'w') as f:
        f.write(data)

But as I said, that only works with *nix systems.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Nick Humrich
  • 14,905
  • 8
  • 62
  • 85
  • 3
    No, there is not a single cross-platform way to create a hidden file, because different operating systems have entirely different implementations. The Windows version basically requires a chattr() call, whereas the UNIX version modifies filenames... how would anyone even _create_ a single abstraction that could reasonably do both those things? – Charles Duffy Aug 21 '14 at 17:15
  • 3
    If your question was how to make a hidden file on Windows from Python, you'd have a better chance of getting an answer. You're not going to find a single abstraction that does both. – Charles Duffy Aug 21 '14 at 17:17
  • This has nothing to do with Python, really, as this is a OS-level problem. A solution that works in Python will work in Perl, Ruby, C, etc. – Martijn Pieters Aug 21 '14 at 17:17
  • possible duplicate of [Python set "hide" attribute on folders in windows OS](http://stackoverflow.com/questions/19622133/python-set-hide-attribute-on-folders-in-windows-os) – Charles Duffy Aug 21 '14 at 17:32

1 Answers1

11

You could do something like this:

import os
import ctypes

FILE_ATTRIBUTE_HIDDEN = 0x02

def write_hidden(file_name, data):
    """
    Cross platform hidden file writer.
    """
    # For *nix add a '.' prefix.
    prefix = '.' if os.name != 'nt' else ''
    file_name = prefix + file_name

    # Write file.
    with open(file_name, 'w') as f:
        f.write(data)

    # For windows set file attribute.
    if os.name == 'nt':
        ret = ctypes.windll.kernel32.SetFileAttributesW(file_name,
                                                        FILE_ATTRIBUTE_HIDDEN)
        if not ret: # There was an error.
            raise ctypes.WinError()

This has not been tested but should work fine.

Also you may wish to see these other questions that helped me implement this:

Community
  • 1
  • 1
luke
  • 1,005
  • 7
  • 19
  • The *nix section should check to make sure the filename doesn't already start with '.' – stark Aug 21 '14 at 20:27
  • 1
    Avoid `ctypes.windll`. It caches function pointers, and other libraries may have defined an incompatible prototype (i.e. `restype`, `argtypes`, and `errcheck`). Also, for reliability you need to use the thread-local captured last error value. Also, you're clobbering existing file attributes. Here's example code taking these observations into account: – Eryk Sun Apr 17 '17 at 02:06
  • 1
    `kernel32 = ctypes.WinDLL('kernel32', use_last_error=True);` `INVALID_FILE_ATTRIBUTES = -1;` `FILE_ATTRIBUTE_HIDDEN = 2;` `attrs = kernel32.GetFileAttributesW(filename)`. `if attrs == -1: raise ctypes.WinError(ctypes.get_last_error())`. `attrs |= FILE_ATTRIBUTE_HIDDEN`. `if not kernel32.SetFileAttributesW(filename, attrs): raise ctypes.WinError(ctypes.get_last_error())`. – Eryk Sun Apr 17 '17 at 02:07