Lista drzewa katalogów w Pythonie


Odpowiedzi:


615

Jest to sposób na przejrzenie każdego pliku i katalogu w drzewie katalogów:

import os

for dirname, dirnames, filenames in os.walk('.'):
    # print path to all subdirectories first.
    for subdirname in dirnames:
        print(os.path.join(dirname, subdirname))

    # print path to all filenames.
    for filename in filenames:
        print(os.path.join(dirname, filename))

    # Advanced usage:
    # editing the 'dirnames' list will stop os.walk() from recursing into there.
    if '.git' in dirnames:
        # don't go into any .git directories.
        dirnames.remove('.git')

19
A jeśli uruchomisz ten kod (tak jak jest) z powłoki Pythona, pamiętaj, że Ctrl + C zatrzyma wyjście do tej powłoki. ;)
Gary

41
Spowoduje to rekurencyjne wyświetlanie plików i katalogów
rds

Możesz nawet edytować listę nazwisk, aby zapobiec ponownemu pojawieniu się niektórych ścieżek.
bugloaf

8
@ Clément "Gdy odgórne ustawienie ma wartość True, dzwoniący może modyfikować listę nazwisk w miejscu (być może przy użyciu przypisania del lub slice), a walk () będzie się powtarzał tylko w podkatalogach, których nazwy pozostają w nazwach nazw; można tego użyć do przycinania wyszukiwać, narzucać określoną kolejność odwiedzin, a nawet informować walk () o katalogach, które wywołujący tworzy lub zmienia nazwy, zanim ponownie podejmie walk (). ” z docs.python.org/2/library/os.html#os.walk
bugloaf

Prostszym sposobem na zignorowanie niektórych katalogów jest nie dodawanie ich do nazwisk w pierwszej kolejnościfor subdirname in dirnames: if subdirname != '.git'
smci

537

Możesz użyć

os.listdir(path)

Dla odniesienia i więcej funkcji OS spójrz tutaj:


1
cóż, pierwotne pytanie jest na tyle niejasne, że nie wiadomo, czy chcieli rozwiązania rekurencyjnego. „wszystkie pliki w katalogu” można interpretować jako rekurencyjne.
Tommy,

3
@Tommy, „katalog” to jasno zdefiniowana struktura danych, która odnosi się raczej do „ls” niż „ls -R”. Poza tym prawie wszystkie narzędzia UNIX domyślnie nie działają rekurencyjnie. Nie wiem, co miał na myśli pytający , ale to, co napisał, było jasne.
Torsten Bronger

Dokumenty Pythona 3 zalecają os.scandirjednak używanie zamiast tego, ponieważ w wielu przypadkach pozwala to zapobiegać wywołaniom systemowym, zapewniając bezpłatne przyspieszenie (zarówno IPC, jak i IO są wolne).
Jappie Kerk

5
listdir podaje jedyną nazwę pliku w katalogu, czy jest dostępna metoda uzyskania pełnej ścieżki?
greperror

1
@greperror Możesz użyć os.path.abspath do uzyskania pełnej ścieżki. Ponadto, aby sprawdzić, czy dana ścieżka jest plikiem, użyj os.path.isfile lub os.path.isdir.
Aleksandar

111

Oto funkcja pomocnika, z której często korzystam:

import os

def listdir_fullpath(d):
    return [os.path.join(d, f) for f in os.listdir(d)]

3
Generator byłby lepszy.
Robert Siemer,

1
@RobertSiemer, który zależy od użytkowania. W wielu przypadkach lista byłaby lepsza, ale myślę, że generator jest bardziej uniwersalny, ponieważ można go przekonwertować na listę. To zależy od tego, czy szukasz, wszechstronności, czy czegoś bardziej usprawnionego.
James Mchugh,

3
Minęło dziesięć lat, ale myślę, że zrobiłem to w ten sposób, ponieważ os.listdir () zwraca listę i naśladowałem ją.
giltay

82
import os

for filename in os.listdir("C:\\temp"):
    print  filename

16
r'C:\temp'jest jaśniejszy i preferowany od "C:\\temp"Rawstringów jest lepszy niż unikanie ukośników odwrotnych.
smci

13

Jeśli potrzebujesz umiejętności globowania, istnieje również moduł do tego. Na przykład:

import glob
glob.glob('./[0-9].*')

zwróci coś takiego:

['./1.gif', './2.txt']

Zobacz dokumentację tutaj .


10

Spróbuj tego:

import os
for top, dirs, files in os.walk('./'):
    for nm in files:       
        print os.path.join(top, nm)

W jednym wierszu: [top + os.sep + f dla góry, reż., Pliki w os.walk ('./') dla f w plikach]
J. Peterson

9

Dla plików w bieżącym katalogu roboczym bez określenia ścieżki

Python 2.7:

import os
os.listdir(os.getcwd())

Python 3.x:

import os
os.listdir()

Dziękujemy Stamowi Kalyowi za komentarz do Pythona 3.x


5
os.listdir()domyślnie wyświetla listę elementów w bieżącym katalogu! Więc nie ma potrzeby os.getcwd():)
Stam Kaly

Jak mam to zrobić? Kiedy używam >>> os.listdir () bez argumentu, dostaję: TypeError: listdir () przyjmuje dokładnie 1 argument (podano 0)
Dave Engineer

2
Zakładam, że korzystasz z wersji 2.7. Ten został dodany 3.x
Stam Kaly

5

Implementacja rekurencyjna

import os

def scan_dir(dir):
    for name in os.listdir(dir):
        path = os.path.join(dir, name)
        if os.path.isfile(path):
            print path
        else:
            scan_dir(path)

3

Napisałem długą wersję ze wszystkimi potrzebnymi opcjami: http://sam.nipl.net/code/python/find.py

Myślę, że tutaj też będzie pasować:

#!/usr/bin/env python

import os
import sys

def ls(dir, hidden=False, relative=True):
    nodes = []
    for nm in os.listdir(dir):
        if not hidden and nm.startswith('.'):
            continue
        if not relative:
            nm = os.path.join(dir, nm)
        nodes.append(nm)
    nodes.sort()
    return nodes

def find(root, files=True, dirs=False, hidden=False, relative=True, topdown=True):
    root = os.path.join(root, '')  # add slash if not there
    for parent, ldirs, lfiles in os.walk(root, topdown=topdown):
        if relative:
            parent = parent[len(root):]
        if dirs and parent:
            yield os.path.join(parent, '')
        if not hidden:
            lfiles   = [nm for nm in lfiles if not nm.startswith('.')]
            ldirs[:] = [nm for nm in ldirs  if not nm.startswith('.')]  # in place
        if files:
            lfiles.sort()
            for nm in lfiles:
                nm = os.path.join(parent, nm)
                yield nm

def test(root):
    print "* directory listing, with hidden files:"
    print ls(root, hidden=True)
    print
    print "* recursive listing, with dirs, but no hidden files:"
    for f in find(root, dirs=True):
        print f
    print

if __name__ == "__main__":
    test(*sys.argv[1:])

3

Oto kolejna opcja.

os.scandir(path='.')

Zwraca iterator obiektów os.DirEntry odpowiadających wpisom (wraz z informacjami o atrybutach pliku) w katalogu podanym przez ścieżkę.

Przykład:

with os.scandir(path) as it:
    for entry in it:
        if not entry.name.startswith('.'):
            print(entry.name)

Użycie scandir () zamiast listdir () może znacznie zwiększyć wydajność kodu, który również potrzebuje informacji o typie pliku lub atrybucie pliku , ponieważ obiekty os.DirEntry ujawniają te informacje, jeśli system operacyjny udostępnia je podczas skanowania katalogu. Wszystkie metody os.DirEntry mogą wykonywać wywołanie systemowe, ale is_dir () i is_file () zwykle wymagają tylko wywołania systemowego dla dowiązań symbolicznych; os.DirEntry.stat () zawsze wymaga wywołania systemowego w systemie Unix, ale wymaga tylko jednego dla dowiązań symbolicznych w systemie Windows.

Python Docs


3

Chociaż os.listdir()generowanie listy nazw plików i katalogów jest w porządku, często po zrobieniu tych nazw chcesz zrobić więcej - aw Pythonie 3 pathlib upraszcza te inne obowiązki. Zobaczmy, czy podoba ci się tak samo jak ja.

Aby wyświetlić zawartość katalogu, zbuduj obiekt Path i chwyć iterator:

In [16]: Path('/etc').iterdir()
Out[16]: <generator object Path.iterdir at 0x110853fc0>

Jeśli chcemy tylko listę nazw rzeczy:

In [17]: [x.name for x in Path('/etc').iterdir()]
Out[17]:
['emond.d',
 'ntp-restrict.conf',
 'periodic',

Jeśli chcesz tylko katalogów:

In [18]: [x.name for x in Path('/etc').iterdir() if x.is_dir()]
Out[18]:
['emond.d',
 'periodic',
 'mach_init.d',

Jeśli chcesz mieć nazwy wszystkich plików conf w tym drzewie:

In [20]: [x.name for x in Path('/etc').glob('**/*.conf')]
Out[20]:
['ntp-restrict.conf',
 'dnsextd.conf',
 'syslog.conf',

Jeśli chcesz listę plików conf w drzewie> = 1K:

In [23]: [x.name for x in Path('/etc').glob('**/*.conf') if x.stat().st_size > 1024]
Out[23]:
['dnsextd.conf',
 'pf.conf',
 'autofs.conf',

Rozwiązywanie względnych ścieżek staje się łatwe:

In [32]: Path('../Operational Metrics.md').resolve()
Out[32]: PosixPath('/Users/starver/code/xxxx/Operational Metrics.md')

Nawigacja za pomocą ścieżki jest dość prosta (choć nieoczekiwana):

In [10]: p = Path('.')

In [11]: core = p / 'web' / 'core'

In [13]: [x for x in core.iterdir() if x.is_file()]
Out[13]:
[PosixPath('web/core/metrics.py'),
 PosixPath('web/core/services.py'),
 PosixPath('web/core/querysets.py'),

1

Przyjemny jeden linijka, aby rekursywnie wyświetlać tylko pliki. Użyłem tego w mojej dyrektywie setup.py pakiet_danych:

import os

[os.path.join(x[0],y) for x in os.walk('<some_directory>') for y in x[2]]

Wiem, że to nie jest odpowiedź na pytanie, ale może się przydać


1

Dla Python 2

#!/bin/python2

import os

def scan_dir(path):
    print map(os.path.abspath, os.listdir(pwd))

Dla Python 3

Aby filtrować i mapować, musisz owinąć je list ()

#!/bin/python3

import os

def scan_dir(path):
    print(list(map(os.path.abspath, os.listdir(pwd))))

Zaleca się teraz, aby zastąpić korzystanie z mapy i filtru wyrażeniami generatorów lub list:

#!/bin/python

import os

def scan_dir(path):
    print([os.path.abspath(f) for f in os.listdir(path)])

1

Oto jednowierszowa wersja w języku Python:

import os
dir = 'given_directory_name'
filenames = [os.path.join(os.path.dirname(os.path.abspath(__file__)),dir,i) for i in os.listdir(dir)]

Ten kod zawiera pełną ścieżkę wszystkich plików i katalogów w podanej nazwie katalogu.


Dzięki Saleh, ale twój kod nie działał w pełni, a ten działał został zmodyfikowany w następujący sposób: 'katalog =' nazwa_katalogu '' nazwy plików = [os.path.abspath (os.path.join (dir, i)) dla i w os.listdir (reż)] '
HassanSh__3571619

1

Wiem, że to stare pytanie. To fajny sposób, z jakim się spotkałem, jeśli używasz maszyny Liunx.

import subprocess
print(subprocess.check_output(["ls", "/"]).decode("utf8"))

0
#import modules
import os

_CURRENT_DIR = '.'


def rec_tree_traverse(curr_dir, indent):
    "recurcive function to traverse the directory"
    #print "[traverse_tree]"

    try :
        dfList = [os.path.join(curr_dir, f_or_d) for f_or_d in os.listdir(curr_dir)]
    except:
        print "wrong path name/directory name"
        return

    for file_or_dir in dfList:

        if os.path.isdir(file_or_dir):
            #print "dir  : ",
            print indent, file_or_dir,"\\"
            rec_tree_traverse(file_or_dir, indent*2)

        if os.path.isfile(file_or_dir):
            #print "file : ",
            print indent, file_or_dir

    #end if for loop
#end of traverse_tree()

def main():

    base_dir = _CURRENT_DIR

    rec_tree_traverse(base_dir," ")

    raw_input("enter any key to exit....")
#end of main()


if __name__ == '__main__':
    main()

5
To pytanie ma już doskonałą odpowiedź, nie ma potrzeby udzielania odpowiedzi ponownie
Mike Pennington

0

FYI Dodaj filtr rozszerzenia pliku importu rozszerzenia lub pliku os

path = '.'
for dirname, dirnames, filenames in os.walk(path):
    # print path to all filenames with extension py.
    for filename in filenames:
        fname_path = os.path.join(dirname, filename)
        fext = os.path.splitext(fname_path)[1]
        if fext == '.py':
            print fname_path
        else:
            continue

0

Jeśli to wymyślone, wrzucę to. Prosty i brudny sposób wyszukiwania symboli wieloznacznych.

import re
import os

[a for a in os.listdir(".") if re.search("^.*\.py$",a)]

0

Poniższy kod wyświetli katalogi i pliki w katalogu

def print_directory_contents(sPath):
        import os                                       
        for sChild in os.listdir(sPath):                
            sChildPath = os.path.join(sPath,sChild)
            if os.path.isdir(sChildPath):
                print_directory_contents(sChildPath)
            else:
                print(sChildPath)

0

Ten, który pracował ze mną, to rodzaj zmodyfikowanej wersji z odpowiedzi Saleha powyżej.

Kod jest następujący:

"katalog =„ nazwa_katalogu_danego ”nazwy plików = [ścieżka.path.abspath (ścieżka.pjo.join (katalog, i)) dla i w katalogu os.listdir (katalog)]”

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.