Як ігнорувати приховані файли за допомогою os.listdir ()?


87

Мій скрипт python виконує os.listdir(path)шлях, де шлях є чергою, що містить архіви, які мені потрібно обробляти по черзі.

Проблема в тому, що я отримую список у масиві, а потім я просто роблю просте array.pop(0). Це працювало нормально, поки я не перевів проект у диверсію. Тепер я отримую .svnпапку у своєму масиві, і, звичайно, це призводить до збою мого додатка.

Тож ось моє запитання: чи існує функція, яка ігнорує приховані файли під час виконання, os.listdir()і як ні, то який найкращий спосіб?

Відповіді:


102

Ви можете написати його самостійно:

def listdir_nohidden(path):
    for f in os.listdir(path):
        if not f.startswith('.'):
            yield f

Або ви можете використовувати глобус :

def listdir_nohidden(path):
    return glob.glob(os.path.join(path, '*'))

Будь-яка з них буде ігнорувати всі імена файлів, що починаються з '.'.


1
запропонована функція listdir_nohiddenне зовсім сумісна з os.listdir, оскільки використання yieldробить її генератором. Натомість він повинен проходити через вихідний список os.listdirі видаляти записи, що починаються на '.'
Майло Вілондек,

3
@ 0sh: Чому він повинен видаляти речі на місці? Просто визначте нову функцію, яка працює, list(listdir_nohidden(path))і ця нова функція точно сумісна з os.listdir.
abarnert

47

Це старе запитання, але, схоже, йому не вистачає очевидної відповіді використання розуміння списку, тому я додаю його тут для повноти:

[f for f in os.listdir(path) if not f.startswith('.')]

Як зауваження, стан документів listdirбуде повертати результати у "довільному порядку", але загальним випадком використання є їх сортування за алфавітом. Якщо ви хочете, щоб вміст каталогу було відсортовано за алфавітом, не враховуючи використання великих літер, ви можете використовувати:

sorted([f for f in os.listdir('./')], key=lambda f: f.lower())

5
key=lambda f: f.lower()можна написати без лямбди:key=str.lower
Жан-Франсуа Фабр

2
Щоб поєднати обидва:sorted([f for f in os.listdir('./') if not f.startswith('.')], key=str.lower)
Роберт

18

У Windows, Linux та OS X:

if os.name == 'nt':
    import win32api, win32con


def folder_is_hidden(p):
    if os.name== 'nt':
        attribute = win32api.GetFileAttributes(p)
        return attribute & (win32con.FILE_ATTRIBUTE_HIDDEN | win32con.FILE_ATTRIBUTE_SYSTEM)
    else:
        return p.startswith('.') #linux-osx

2
також повинен працювати на Mac, приховані файли починаються там з "." так само.
Верена Хауншмід

2
Це єдина портативна відповідь, чудова робота, але інші відповіді забезпечують повну обгортку для os.listdir, так що ...[f for f in os.listdir(path) if not folder_is_hidden(f)]
SensorSmith


14

глобус :

>>> import glob
>>> glob.glob('*')

( globпретендує на використання listdirі fnmatchпід капотом, але він також перевіряє наявність ведучого '.', а не за допомогою fnmatch.)


6

Я думаю, що це занадто багато роботи, щоб переглядати всі елементи в циклі. Я віддав би перевагу чомусь такому простішому:

lst = os.listdir(path)
if '.DS_Store' in lst:
    lst.remove('.DS_Store')

Якщо каталог містить більше одного прихованого файлу , це може допомогти:

all_files = os.popen('ls -1').read()
lst = all_files.split('\n')

для незалежності платформи, як @Josh згадав, що glob працює добре:

import glob
glob.glob('*')

Це працює, лише якщо у вас є один прихований файл, і ви знаєте його назву. Що робити, якщо каталог містить десятки прихованих файлів із довільними назвами, які ви не можете знати заздалегідь?
FeRD

Привіт @FeRD, так. Коли я роблю пакетну обробку / відставання на Mac, я поміщаю всі файли в нову папку і .DS_Storeстворюється автоматично. Коли я стискаю всі файли в архів і надсилаю їх на сервер, .DS_Storeтакож додається. Якщо є різні приховані файли, можливо, ви можете спробуватиos.system('ls -1')
користувач 923227

Не крос-платформний. os.popen('ls -1').read()не буде працювати в Windows. У цьому вся суть os.listdir().
FeRD

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.