os.listdir()você terá tudo o que está em um diretório - arquivos e diretórios .
Se você quiser apenas arquivos, poderá filtrar isso usando os.path:
from os import listdir
from os.path import isfile, join
onlyfiles =[f for f in listdir(mypath)if isfile(join(mypath, f))]
ou você pode usar o os.walk()que produzirá duas listas para cada diretório visitado - dividindo-se em arquivos e diretórios para você. Se você deseja apenas o diretório superior, basta interromper a primeira vez que ele produzir
from os import walk
f =[]for(dirpath, dirnames, filenames)in walk(mypath):
f.extend(filenames)break
Um pouco mais simples: (_, _, filenames) = walk(mypath).next() (se você está confiante de que a caminhada irá retornar pelo menos um valor, que deveria.)
misterbee
9
Pequena modificação para armazenar caminhos completos: para (caminho de caminho, nomes de arquivos, nomes de arquivos) no os.walk (caminho do meu): checksum_files.extend (os.path.join (caminho do arquivo, nome do arquivo) para o nome do arquivo nos nomes de arquivos) break
okigan
150
f.extend(filenames)não é realmente equivalente a f = f + filenames. extendserá modificado fno local, enquanto a adição cria uma nova lista em um novo local de memória. Isso significa que extendgeralmente é mais eficiente que +, mas às vezes pode causar confusão se vários objetos mantiverem referências à lista. Por fim, vale a pena notar que isso f += filenamesé equivalente a f.extend(filenames), nãof = f + filenames .
Benjamin Hodgson
30
@misterbee, sua solução é a melhor, apenas uma pequena melhoria:_, _, filenames = next(walk(mypath), (None, None, []))
bgusach
35
no uso do python 3.x(_, _, filenames) = next(os.walk(mypath))
ET-CS
1683
Eu prefiro usar o globmódulo, pois combina correspondência e expansão de padrões.
import glob
print(glob.glob("/home/adam/*.txt"))
Ele retornará uma lista com os arquivos consultados:
para esclarecer, isso não retorna o "caminho completo"; simplesmente retorna a expansão da glob, seja ela qual for. Por exemplo, dado que /home/user/foo/bar/hello.txt, se estiver sendo executado no diretório foo, o valor glob("bar/*.txt")retornará bar/hello.txt. Há casos em que você realmente deseja o caminho completo (ou seja, absoluto); para esses casos, consulte stackoverflow.com/questions/51520/…
não responde a essa pergunta. glob.glob("*")seria.
Jean-François Fabre
bonita!!!! então .... x=glob.glob("../train/*.png")me dará uma matriz dos meus caminhos, desde que eu saiba o nome da pasta. Tão legal!
Jennifer Crosby
859
Obtenha uma lista de arquivos com Python 2 e 3
os.listdir()
Como obter todos os arquivos (e diretórios) no diretório atual (Python 3)
A seguir, são métodos simples para recuperar apenas arquivos no diretório atual, usando os e a listdir()função, no Python 3. Explorações adicionais demonstrarão como retornar pastas no diretório, mas você não terá o arquivo no subdiretório, para o qual você pode usar o walk - discutido mais tarde).
import os
arr = os.listdir()print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
glob
Achei a glob mais fácil de selecionar o arquivo do mesmo tipo ou com algo em comum. Veja o seguinte exemplo:
import glob
txtfiles =[]for file in glob.glob("*.txt"):
txtfiles.append(file)
glob com compreensão de lista
import glob
mylist =[f for f in glob.glob("*.txt")]
glob com uma função
A função retorna uma lista da extensão fornecida (.txt, .docx ecc.) No argumento
import glob
def filebrowser(ext=""):"Returns files with an extension"return[f for f in glob.glob(f"*{ext}")]
x = filebrowser(".txt")print(x)>>>['example.txt','fb.txt','intro.txt','help.txt']
glob estendendo o código anterior
A função agora retorna uma lista de arquivos que correspondem à string que você passa como argumento
import glob
def filesearch(word=""):"""Returns a list with all files with the word/extension in it"""
file =[]for f in glob.glob("*"):if word[0]==".":if f.endswith(word):
file.append(f)return file
elif word in f:
file.append(f)return file
return file
lookfor ="example",".py"for w in lookfor:print(f"{w:10} found => {filesearch(w)}")
resultado
example found =>[].py found =>['search.py']
Obter o nome completo do caminho com os.path.abspath
Como você notou, você não tem o caminho completo do arquivo no código acima. Se você precisar ter o caminho absoluto, poderá usar outra função do os.pathmódulo chamada _getfullpathname, colocando o arquivo que obtém os.listdir()como argumento. Existem outras maneiras de ter o caminho completo, como verificaremos mais tarde (substituí, como sugerido por mexmex, _getfullpathname with abspath).
import os
files_path =[os.path.abspath(x)for x in os.listdir()]print(files_path)>>>['F:\\documenti\applications.txt','F:\\documenti\collections.txt']
Obtenha o nome completo do caminho de um tipo de arquivo em todos os subdiretórios com walk
Acho isso muito útil para encontrar coisas em muitos diretórios e me ajudou a encontrar um arquivo sobre o qual não me lembrava do nome:
import os
# Getting the current work directory (cwd)
thisdir = os.getcwd()# r=root, d=directories, f = filesfor r, d, f in os.walk(thisdir):for file in f:if file.endswith(".docx"):print(os.path.join(r, file))
os.listdir(): obtém arquivos no diretório atual (Python 2)
No Python 2, se você quiser a lista dos arquivos no diretório atual, precisará fornecer o argumento como '.' ou os.getcwd () no método os.listdir.
import os
arr = os.listdir('.')print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
Para subir na árvore de diretórios
# Method 1
x = os.listdir('..')# Method 2
x= os.listdir('/')
Obter arquivos: os.listdir()em um diretório específico (Python 2 e 3)
import os
arr = os.listdir('F:\\python')print(arr)>>>['$RECYCLE.BIN','work.txt','3ebooks.txt','documents']
Obter arquivos de um subdiretório específico com os.listdir()
import os
x = os.listdir("./content")
os.walk('.') - diretório atual
import os
arr = next(os.walk('.'))[2]print(arr)>>>['5bs_Turismo1.pdf','5bs_Turismo1.pptx','esperienza.txt']
next(os.walk('.')) e os.path.join('dir', 'file')
import os
arr =[]for d,r,f in next(os.walk("F:\\_python")):for file in f:
arr.append(os.path.join(r,file))for f in arr:print(files)>>> F:\\_python\\dict_class.py
>>> F:\\_python\\programmi.txt
next(os.walk('F:\\') - obtenha o caminho completo - compreensão da lista
[os.path.join(r,file)for r,d,f in next(os.walk("F:\\_python"))for file in f]>>>['F:\\_python\\dict_class.py','F:\\_python\\programmi.txt']
os.walk - obtém o caminho completo - todos os arquivos em subdiretórios **
x =[os.path.join(r,file)for r,d,f in os.walk("F:\\_python")for file in f]print(x)>>>['F:\\_python\\dict.py','F:\\_python\\progr.txt','F:\\_python\\readl.py']
os.listdir() - obtenha apenas arquivos txt
arr_txt =[x for x in os.listdir()if x.endswith(".txt")]print(arr_txt)>>>['work.txt','3ebooks.txt']
Usando globpara obter o caminho completo dos arquivos
Se eu precisar do caminho absoluto dos arquivos:
from path import path
from glob import glob
x =[path(f).abspath()for f in glob("F:\\*.txt")]for f in x:print(f)>>> F:\acquistionline.txt
>>> F:\acquisti_2018.txt
>>> F:\bootstrap_jquery_ecc.txt
Usando os.path.isfilepara evitar diretórios na lista
import os.path
listOfFiles =[f for f in os.listdir()if os.path.isfile(f)]print(listOfFiles)>>>['a simple game.py','data.txt','decorator.py']
Usando pathlibdo Python 3.4
import pathlib
flist =[]for p in pathlib.Path('.').iterdir():if p.is_file():print(p)
flist.append(p)>>> error.PNG
>>> exemaker.bat
>>> guiprova.mp3
>>> setup.py
>>> speak_gui2.py
>>> thumb.PNG
Com list comprehension:
flist =[p for p in pathlib.Path('.').iterdir()if p.is_file()]
Como alternativa, use em pathlib.Path()vez depathlib.Path(".")
import os
x =[i[2]for i in os.walk('.')]
y=[]for t in x:for f in t:
y.append(f)print(y)>>>['append_to_list.py','data.txt','data1.txt','data2.txt','data_180617','os_walk.py','READ2.py','read_data.py','somma_defaltdic.py','substitute_words.py','sum_data.py','data.txt','data1.txt','data_180617']
Obtenha apenas arquivos com o próximo e entre em um diretório
import os
x = next(os.walk('F://python'))[2]print(x)>>>['calculator.bat','calculator.py']
Obtenha apenas diretórios com o próximo e entre em um diretório
import os
next(os.walk('F://python'))[1]# for the current dir use ('.')>>>['python3','others']
Obtenha todos os nomes dos subdiretórios com walk
for r,d,f in os.walk("F:\\_python"):for dirs in d:print(dirs)>>>.vscode
>>> pyexcel
>>> pyschool.py
>>> subtitles
>>> _metaprogramming
>>>.ipynb_checkpoints
os.scandir() do Python 3.5 e superior
import os
x =[f.name for f in os.scandir()if f.is_file()]print(x)>>>['calculator.bat','calculator.py']# Another example with scandir (a little variation from docs.python.org)# This one is more efficient than os.listdir.# In this case, it shows the files only in the current directory# where the script is executed.import os
with os.scandir()as i:for entry in i:if entry.is_file():print(entry.name)>>> ebookmaker.py
>>> error.PNG
>>> exemaker.bat
>>> guiprova.mp3
>>> setup.py
>>> speakgui4.py
>>> speak_gui2.py
>>> speak_gui3.py
>>> thumb.PNG
Exemplos:
Ex. 1: Quantos arquivos existem nos subdiretórios?
Neste exemplo, procuramos o número de arquivos incluídos em todo o diretório e seus subdiretórios.
import os
def count(dir, counter=0):"returns number of files in dir and subdirs"for pack in os.walk(dir):for f in pack[2]:
counter +=1return dir +" : "+ str(counter)+"files"print(count("F:\\python"))>>>'F:\\\python':12057 files'
Ex.2: Como copiar todos os arquivos de um diretório para outro?
Um script para fazer o pedido em seu computador, localizando todos os arquivos de um tipo (padrão: pptx) e copiando-os em uma nova pasta.
import os
import shutil
from path import path
destination ="F:\\file_copied"# os.makedirs(destination)def copyfile(dir, filetype='pptx', counter=0):"Searches for pptx (or other - pptx is the default) files and copies them"for pack in os.walk(dir):for f in pack[2]:if f.endswith(filetype):
fullpath = pack[0]+"\\"+ f
print(fullpath)
shutil.copy(fullpath, destination)
counter +=1if counter >0:print('-'*30)print("\t==> Found in: `"+ dir +"` : "+ str(counter)+" files\n")for dir in os.listdir():"searches for folders that starts with `_`"if dir[0]=='_':# copyfile(dir, filetype='pdf')
copyfile(dir, filetype='txt')>>> _compiti18\Compito Contabilità1\conti.txt
>>> _compiti18\Compito Contabilità1\modula4.txt
>>> _compiti18\Compito Contabilità1\moduloa4.txt
>>>------------------------>>>==>Foundin:`_compiti18`:3 files
Ex. 3: Como obter todos os arquivos em um arquivo txt
Caso você queira criar um arquivo txt com todos os nomes de arquivos:
import os
mylist =""with open("filelist.txt","w", encoding="utf-8")as file:for eachfile in os.listdir():
mylist += eachfile +"\n"
file.write(mylist)
Exemplo: txt com todos os arquivos de um disco rígido
"""
We are going to save a txt file with all the files in your directory.
We will use the function walk()
"""import os
# see all the methods of os# print(*dir(os), sep=", ")
listafile =[]
percorso =[]with open("lista_file.txt","w", encoding='utf-8')as testo:for root, dirs, files in os.walk("D:\\"):for file in files:
listafile.append(file)
percorso.append(root +"\\"+ file)
testo.write(file +"\n")
listafile.sort()print("N. of files", len(listafile))with open("lista_file_ordinata.txt","w", encoding="utf-8")as testo_ordinato:for file in listafile:
testo_ordinato.write(file +"\n")with open("percorso.txt","w", encoding="utf-8")as file_percorso:for file in percorso:
file_percorso.write(file +"\n")
os.system("lista_file.txt")
os.system("lista_file_ordinata.txt")
os.system("percorso.txt")
Todo o arquivo de C: \ em um arquivo de texto
Esta é uma versão mais curta do código anterior. Mude a pasta onde começar a encontrar os arquivos, se precisar começar de outra posição. Esse código gera um arquivo de texto de 50 mb no meu computador com algo menos de 500.000 linhas com arquivos com o caminho completo.
import os
with open("file.txt","w", encoding="utf-8")as filewrite:for r, d, f in os.walk("C:\\"):for file in f:
filewrite.write(f"{r + file}\n")
Como gravar um arquivo com todos os caminhos em uma pasta de um tipo
Com esta função, você pode criar um arquivo txt que terá o nome de um tipo de arquivo que você procura (por exemplo, pngfile.txt) com todo o caminho completo de todos os arquivos desse tipo. Às vezes, pode ser útil, eu acho.
import os
def searchfiles(extension='.ttf', folder='H:\\'):"Create a txt file with all the file of a type"with open(extension[1:]+"file.txt","w", encoding="utf-8")as filewrite:for r, d, f in os.walk(folder):for file in f:if file.endswith(extension):
filewrite.write(f"{r + file}\n")# looking for png file (fonts) in the hard disk H:\
searchfiles('.png','H:\\')>>> H:\4bs_18\Dolphins5.png
>>> H:\4bs_18\Dolphins6.png
>>> H:\4bs_18\Dolphins7.png
>>> H:\5_18\marketing html\assets\imageslogo2.png
>>> H:\7z001.png
>>> H:\7z002.png
(Novo) Encontre todos os arquivos e abra-os com tkinter GUI
Eu só queria adicionar neste 2019 um pequeno aplicativo para procurar todos os arquivos em um diretório e poder abri-los clicando duas vezes no nome do arquivo na lista.
import tkinter as tk
import os
def searchfiles(extension='.txt', folder='H:\\'):"insert all files in the listbox"for r, d, f in os.walk(folder):for file in f:if file.endswith(extension):
lb.insert(0, r +"\\"+ file)def open_file():
os.startfile(lb.get(lb.curselection()[0]))
root = tk.Tk()
root.geometry("400x400")
bt = tk.Button(root, text="Search", command=lambda:searchfiles('.png','H:\\'))
bt.pack()
lb = tk.Listbox(root)
lb.pack(fill="both", expand=1)
lb.bind("<Double-Button>",lambda x: open_file())
root.mainloop()
Esta é uma mistura de muitas respostas para perguntas não feitas aqui. Também pode valer a pena explicar quais são as advertências ou abordagens recomendadas. Não é melhor conhecer uma maneira versus 20 maneiras de fazer a mesma coisa, a menos que eu também saiba qual é mais apropriado usar quando.
cs95 27/01
Ok, o mais rápido possível Vou dar uma olhada na minha resposta e tentar torná-la mais limpa e com informações mais úteis sobre a diferença entre os métodos etc.
Giovanni G. PY
Você não deve determinar a extensão do arquivo verificando se o nome do arquivo contém uma substring. Isso pode causar muitos problemas. Eu recomendo sempre verificar se o nome do arquivo termina com a substring específica.
ni1ight 2/03
Ok, @ n1light eu mudei o código ...
Giovanni G. PY
812
import os
os.listdir("somedirectory")
retornará uma lista de todos os arquivos e diretórios no "somedirectory".
Isso retorna o caminho relativo dos arquivos, em comparação com o caminho completo retornado porglob.glob
xji 17/16
22
@ JIXiang: os.listdir()sempre retorna meros nomes de arquivos (não caminhos relativos). O glob.glob()retorno é conduzido pelo formato do caminho do padrão de entrada.
mklement0
os.listdir () -> Sempre lista o diretório e o arquivo dentro do local fornecido. Existe alguma maneira de listar apenas diretório e não arquivos?
Ronya
160
Uma solução de uma linha para obter apenas a lista de arquivos (sem subdiretórios):
filenames = next(os.walk(path))[2]
ou caminhos absolutos:
paths =[os.path.join(path, fn)for fn in next(os.walk(path))[2]]
Apenas uma linha, se você já tiver import os. Parece menos conciso do que glob()para mim.
ArtOfWarfare 28/11
4
problema com glob é que uma pasta chamada 'something.something' seria devolvido por glob ( '/ home / adam /*.*')
Remi
6
No OS X, há algo chamado pacote. É um diretório que geralmente deve ser tratado como um arquivo (como um .tar). Você gostaria que aqueles tratados como um arquivo ou um diretório? Usar glob()o trataria como um arquivo. Seu método o trataria como um diretório.
ArtOfWarfare
132
Obtendo caminhos de arquivo completos de um diretório e de todos os seus subdiretórios
import os
def get_filepaths(directory):"""
This function will generate the file names in a directory
tree by walking the tree either top-down or bottom-up. For each
directory in the tree rooted at directory top (including top itself),
it yields a 3-tuple (dirpath, dirnames, filenames).
"""
file_paths =[]# List which will store all of the full filepaths.# Walk the tree.for root, directories, files in os.walk(directory):for filename in files:# Join the two strings in order to form the full filepath.
filepath = os.path.join(root, filename)
file_paths.append(filepath)# Add it to the list.return file_paths # Self-explanatory.# Run the above function and store its results in a variable.
full_file_paths = get_filepaths("/Users/johnny/Desktop/TEST")
O caminho que forneci na função acima continha 3 arquivos - dois no diretório raiz e outro em uma subpasta chamada "SUBFOLDER". Agora você pode fazer coisas como:
>>>import pathlib
>>>[p for p in pathlib.Path('.').iterdir()if p.is_file()]
De acordo com o PEP 428 , o objetivo da pathlibbiblioteca é fornecer uma hierarquia simples de classes para manipular os caminhos do sistema de arquivos e as operações comuns que os usuários fazem sobre eles.
Obrigado! Eu acho que é a única solução que não retorna diretamente a list. Poderia usar em p.namevez do primeiro palternativamente, se preferir.
jeromej
1
Bem-vinda! Eu preferiria gerar pathlib.Path()instâncias, pois eles têm muitos métodos úteis que eu não gostaria de desperdiçar. Você também pode chamá str(p)-los para nomes de caminhos.
SzieberthAdam
6
Nota: A os.scandirsolução será mais eficiente do que os.listdircom uma os.path.is_fileverificação ou algo parecido, mesmo se você precisar de uma list(para que você não se beneficie da iteração lenta), porque os.scandirusa APIs fornecidas pelo SO que fornecem is_fileinformações gratuitamente enquanto itera , não por arquivo de ida e volta para o disco para stateles em tudo (no Windows, os DirEntrys te completa statinformações de graça, em sistemas * NIX ele precisa statde informações para além is_file, is_diretc., mas DirEntrycaches na primeira statpor conveniência).
ShadowRanger #
1
Você também pode usar entry.namepara obter apenas o nome do arquivo ou entry.pathpara obter o caminho completo. Não há mais os.path.join () em todo o lugar.
user136036
56
Notas preliminares
Embora exista uma clara diferenciação entre os termos de arquivo e diretório no texto da pergunta, alguns podem argumentar que os diretórios são realmente arquivos especiais
A declaração: " todos os arquivos de um diretório " podem ser interpretados de duas maneiras:
Todos os descendentes diretos (ou nível 1) apenas
Todos os descendentes em toda a árvore de diretórios (incluindo os subdiretórios)
Quando a pergunta foi feita, imagino que o Python 2 fosse a versão LTS , no entanto, os exemplos de código serão executados pelo Python 3 ( .5 ) (eu os manterei o mais compatível possível com o Python 2 ; também, qualquer código pertencente a O Python que vou postar é da v3.5.4 - a menos que seja especificado de outra forma). Isso tem consequências relacionadas a outra palavra-chave na pergunta: " adicione-as a uma lista ":
No pré- Python 2.2 versões , as sequências (iteráveis) eram representadas principalmente por listas (tuplas, conjuntos, ...)
No Python 2.2 , o conceito de gerador ( [Python.Wiki]: Generators ) - cortesia de [Python 3]: A declaração de rendimento ) - foi introduzido. Com o passar do tempo, as contrapartes do gerador começaram a aparecer para funções que retornavam / trabalhavam com listas
No Python 3 , gerador é o comportamento padrão
Não tenho certeza se o retorno de uma lista ainda é obrigatório (ou um gerador faria também), mas passar um gerador para o construtor da lista criará uma lista a partir dela (e também a consumirá). O exemplo abaixo ilustra as diferenças em [Python 3]: map ( function, iterable, ... )
>>>import sys
>>> sys.version
'2.7.10 (default, Mar 8 2016, 15:02:46) [MSC v.1600 64 bit (AMD64)]'>>> m = map(lambda x: x,[1,2,3])# Just a dummy lambda function>>> m, type(m)([1,2,3],<type 'list'>)>>> len(m)3
>>>import sys
>>> sys.version
'3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)]'>>> m = map(lambda x: x,[1,2,3])>>> m, type(m)(<map object at 0x000001B4257342B0>,<class'map'>)>>> len(m)Traceback(most recent call last):File"<stdin>", line 1,in<module>TypeError: object of type 'map' has no len()>>> lm0 = list(m)# Build a list from the generator>>> lm0, type(lm0)([1,2,3],<class'list'>)>>>>>> lm1 = list(m)# Build a list from the same generator>>> lm1, type(lm1)# Empty list now - generator already consumed([],<class'list'>)
Os exemplos serão baseados em um diretório chamado root_dir com a seguinte estrutura (este exemplo é para Win , mas também estou usando a mesma árvore no Lnx ):
Retorne uma lista contendo os nomes das entradas no diretório fornecido pelo caminho. A lista está em ordem arbitrária e não inclui as entradas especiais '.'e '..'...
>>>import os
>>> root_dir ="root_dir"# Path relative to current dir (os.getcwd())>>>>>> os.listdir(root_dir)# List all the items in root_dir['dir0','dir1','dir2','dir3','file0','file1']>>>>>>[item for item in os.listdir(root_dir)if os.path.isfile(os.path.join(root_dir, item))]# Filter items and only keep files (strip out directories)['file0','file1']
Um exemplo mais elaborado ( code_os_listdir.py ):
import os
from pprint import pformat
def _get_dir_content(path, include_folders, recursive):
entries = os.listdir(path)for entry in entries:
entry_with_path = os.path.join(path, entry)if os.path.isdir(entry_with_path):if include_folders:yield entry_with_path
if recursive:for sub_entry in _get_dir_content(entry_with_path, include_folders, recursive):yield sub_entry
else:yield entry_with_path
def get_dir_content(path, include_folders=True, recursive=True, prepend_folder_name=True):
path_len = len(path)+ len(os.path.sep)for item in _get_dir_content(path, include_folders, recursive):yield item if prepend_folder_name else item[path_len:]def _get_dir_content_old(path, include_folders, recursive):
entries = os.listdir(path)
ret = list()for entry in entries:
entry_with_path = os.path.join(path, entry)if os.path.isdir(entry_with_path):if include_folders:
ret.append(entry_with_path)if recursive:
ret.extend(_get_dir_content_old(entry_with_path, include_folders, recursive))else:
ret.append(entry_with_path)return ret
def get_dir_content_old(path, include_folders=True, recursive=True, prepend_folder_name=True):
path_len = len(path)+ len(os.path.sep)return[item if prepend_folder_name else item[path_len:]for item in _get_dir_content_old(path, include_folders, recursive)]def main():
root_dir ="root_dir"
ret0 = get_dir_content(root_dir, include_folders=True, recursive=True, prepend_folder_name=True)
lret0 = list(ret0)print(ret0, len(lret0), pformat(lret0))
ret1 = get_dir_content_old(root_dir, include_folders=False, recursive=True, prepend_folder_name=False)print(len(ret1), pformat(ret1))if __name__ =="__main__":
main()
Notas :
Existem duas implementações:
Um que usa geradores (é claro que aqui parece inútil, pois eu imediatamente converto o resultado em uma lista)
O clássico (nomes de funções que terminam em _old )
A recursão é usada (para entrar nos subdiretórios)
Para cada implementação, existem duas funções:
Um que começa com um sublinhado ( _ ): "privado" (não deve ser chamado diretamente) - faz todo o trabalho
O público (wrapper sobre o anterior): apenas retira o caminho inicial (se necessário) das entradas retornadas. É uma implementação feia, mas é a única ideia que eu poderia ter neste momento
Em termos de desempenho, os geradores geralmente são um pouco mais rápidos (considerando a criação e a iteração tempos de ), mas eu não os testei em funções recursivas e também estou interagindo dentro da função por geradores internos - não sei como o desempenho amigável é isso
Brinque com os argumentos para obter resultados diferentes
Saída :
(py35x64_test) E:\Work\Dev\StackOverflow\q003207219>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe""code_os_listdir.py"<generator object get_dir_content at 0x000001BDDBB3DF10>22['root_dir\\dir0','root_dir\\dir0\\dir00','root_dir\\dir0\\dir00\\dir000','root_dir\\dir0\\dir00\\dir000\\file0000','root_dir\\dir0\\dir00\\file000','root_dir\\dir0\\dir01','root_dir\\dir0\\dir01\\file010','root_dir\\dir0\\dir01\\file011','root_dir\\dir0\\dir02','root_dir\\dir0\\dir02\\dir020','root_dir\\dir0\\dir02\\dir020\\dir0200','root_dir\\dir1','root_dir\\dir1\\file10','root_dir\\dir1\\file11','root_dir\\dir1\\file12','root_dir\\dir2','root_dir\\dir2\\dir20','root_dir\\dir2\\dir20\\file200','root_dir\\dir2\\file20','root_dir\\dir3','root_dir\\file0','root_dir\\file1']11['dir0\\dir00\\dir000\\file0000','dir0\\dir00\\file000','dir0\\dir01\\file010','dir0\\dir01\\file011','dir1\\file10','dir1\\file11','dir1\\file12','dir2\\dir20\\file200','dir2\\file20','file0','file1']
Retorne um iterador de objetos os.DirEntry correspondentes às entradas no diretório fornecidas pelo caminho . As entradas são produzidas em ordem arbitrária e as entradas especiais '.'e '..'não estão incluídas.
Usar scandir () em vez de listdir () pode aumentar significativamente o desempenho do código que também precisa de informações sobre o tipo ou o atributo do arquivo, porque os objetos os.DirEntry expõem essas informações se o sistema operacional as fornecer ao varrer um diretório. Todos os métodos os.DirEntry podem executar uma chamada do sistema, mas is_dir () e is_file () geralmente requerem apenas uma chamada do sistema para links simbólicos; os.DirEntry.stat () sempre requer uma chamada do sistema no Unix, mas apenas uma para links simbólicos no Windows.
>>>import os
>>> root_dir = os.path.join(".","root_dir")# Explicitly prepending current directory>>> root_dir
'.\\root_dir'>>>>>> scandir_iterator = os.scandir(root_dir)>>> scandir_iterator
<nt.ScandirIterator object at 0x00000268CF4BC140>>>>[item.path for item in scandir_iterator]['.\\root_dir\\dir0','.\\root_dir\\dir1','.\\root_dir\\dir2','.\\root_dir\\dir3','.\\root_dir\\file0','.\\root_dir\\file1']>>>>>>[item.path for item in scandir_iterator]# Will yield an empty list as it was consumed by previous iteration (automatically performed by the list comprehension)[]>>>>>> scandir_iterator = os.scandir(root_dir)# Reinitialize the generator>>>for item in scandir_iterator :...if os.path.isfile(item.path):...print(item.name)...
file0
file1
Notas :
É semelhante a os.listdir
Mas também é mais flexível (e oferece mais funcionalidades), mais Python ic (e, em alguns casos, mais rápido)
Gere os nomes de arquivo em uma árvore de diretórios, percorrendo a árvore de cima para baixo ou de baixo para cima. Para cada diretório na árvore com raiz no diretório superior (incluindo top si), ele produz um 3-tupla ( dirpath, dirnames, filenames).
>>>import os
>>> root_dir = os.path.join(os.getcwd(),"root_dir")# Specify the full path>>> root_dir
'E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir'>>>>>> walk_generator = os.walk(root_dir)>>> root_dir_entry = next(walk_generator)# First entry corresponds to the root dir (passed as an argument)>>> root_dir_entry
('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir',['dir0','dir1','dir2','dir3'],['file0','file1'])>>>>>> root_dir_entry[1]+ root_dir_entry[2]# Display dirs and files (direct descendants) in a single list['dir0','dir1','dir2','dir3','file0','file1']>>>>>>[os.path.join(root_dir_entry[0], item)for item in root_dir_entry[1]+ root_dir_entry[2]]# Display all the entries in the previous list by their full path['E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file0','E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\file1']>>>>>>for entry in walk_generator:# Display the rest of the elements (corresponding to every subdir)...print(entry)...('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0',['dir00','dir01','dir02'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00',['dir000'],['file000'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir00\\dir000',[],['file0000'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir01',[],['file010','file011'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02',['dir020'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020',['dir0200'],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir0\\dir02\\dir020\\dir0200',[],[])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir1',[],['file10','file11','file12'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2',['dir20'],['file20'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir2\\dir20',[],['file200'])('E:\\Work\\Dev\\StackOverflow\\q003207219\\root_dir\\dir3',[],[])
Notas :
Nos bastidores, ele usa os.scandir( os.listdirem versões mais antigas)
Retorne uma lista possivelmente vazia de nomes de caminhos que correspondem ao nome do caminho , que deve ser uma sequência contendo uma especificação de caminho. o nome do caminho pode ser absoluto (curtir /usr/src/Python-1.5/Makefile) ou relativo (curtir ../../Tools/*/*.gif) e pode conter curingas no estilo de shell. Links simbólicos quebrados estão incluídos nos resultados (como no shell). ... Alterado na versão 3.5 : Suporte para globs recursivos usando “ **”.
>>>import glob, os
>>> wildcard_pattern ="*">>> root_dir = os.path.join("root_dir", wildcard_pattern)# Match every file/dir name>>> root_dir
'root_dir\\*'>>>>>> glob_list = glob.glob(root_dir)>>> glob_list
['root_dir\\dir0','root_dir\\dir1','root_dir\\dir2','root_dir\\dir3','root_dir\\file0','root_dir\\file1']>>>>>>[item.replace("root_dir"+ os.path.sep,"")for item in glob_list]# Strip the dir name and the path separator from begining['dir0','dir1','dir2','dir3','file0','file1']>>>>>>for entry in glob.iglob(root_dir +"*", recursive=True):...print(entry)...
root_dir\
root_dir\dir0
root_dir\dir0\dir00
root_dir\dir0\dir00\dir000
root_dir\dir0\dir00\dir000\file0000
root_dir\dir0\dir00\file000
root_dir\dir0\dir01
root_dir\dir0\dir01\file010
root_dir\dir0\dir01\file011
root_dir\dir0\dir02
root_dir\dir0\dir02\dir020
root_dir\dir0\dir02\dir020\dir0200
root_dir\dir1
root_dir\dir1\file10
root_dir\dir1\file11
root_dir\dir1\file12
root_dir\dir2
root_dir\dir2\dir20
root_dir\dir2\dir20\file200
root_dir\dir2\file20
root_dir\dir3
root_dir\file0
root_dir\file1
Notas :
Usos os.listdir
Para árvores grandes (especialmente se a recursiva estiver ativada ), é preferível o iglob
Permite filtragem avançada com base no nome (devido ao curinga)
>>>import pathlib
>>> root_dir ="root_dir">>> root_dir_instance = pathlib.Path(root_dir)>>> root_dir_instance
WindowsPath('root_dir')>>> root_dir_instance.name
'root_dir'>>> root_dir_instance.is_dir()True>>>>>>[item.name for item in root_dir_instance.glob("*")]# Wildcard searching for all direct descendants['dir0','dir1','dir2','dir3','file0','file1']>>>>>>[os.path.join(item.parent.name, item.name)for item in root_dir_instance.glob("*")ifnot item.is_dir()]# Display paths (including parent) for files only['root_dir\\file0','root_dir\\file1']
def listdir(path):"""List directory contents, using cache."""try:
cached_mtime, list = cache[path]del cache[path]exceptKeyError:
cached_mtime, list =-1,[]
mtime = os.stat(path).st_mtime
if mtime != cached_mtime:
list = os.listdir(path)
list.sort()
cache[path]= mtime, list
return list
ctypes é uma biblioteca de funções estrangeira para Python. Ele fornece tipos de dados compatíveis com C e permite funções de chamada em DLLs ou bibliotecas compartilhadas. Ele pode ser usado para agrupar essas bibliotecas em Python puro.
LinuxDirent64 é a representação ctypes de struct dirent64 de [man7]: dirent.h (0P) (assim como o constantes DT_ ) da minha máquina: Ubtu 16 x64 ( 4.10.0-40-generic e libc6-dev: amd64 ). Em outros tipos / versões, a definição da estrutura pode ser diferente e, se for o caso, o alias do ctypes deve ser atualizado, caso contrário, resultará em Comportamento indefinido
Retorna dados no os.walkformato do. Eu não me incomodei em torná-lo recursivo, mas a partir do código existente, isso seria uma tarefa bastante trivial
Tudo é possível no Win também, os dados (bibliotecas, funções, estruturas, constantes, ...) diferem
Saída :
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q003207219]>./code_ctypes.py
3.5.2(default,Nov122018,13:43:14)[GCC 5.4.020160609] on linux
['root_dir',['dir2','dir1','dir3','dir0'],['file1','file0']]
Recupera uma lista de nomes de arquivos correspondentes, usando a API Unicode do Windows. Uma interface para as funções de fechamento da API FindFirstFileW / FindNextFileW / Find.
>>>import os, win32file, win32con
>>> root_dir ="root_dir">>> wildcard ="*">>> root_dir_wildcard = os.path.join(root_dir, wildcard)>>> entry_list = win32file.FindFilesW(root_dir_wildcard)>>> len(entry_list)# Don't display the whole content as it's too long8>>>[entry[-2]for entry in entry_list]# Only display the entry names['.','..','dir0','dir1','dir2','dir3','file0','file1']>>>>>>[entry[-2]for entry in entry_list if entry[0]& win32con.FILE_ATTRIBUTE_DIRECTORY and entry[-2]notin(".","..")]# Filter entries and only display dir names (except self and parent)['dir0','dir1','dir2','dir3']>>>>>>[os.path.join(root_dir, entry[-2])for entry in entry_list if entry[0]&(win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_ATTRIBUTE_ARCHIVE)]# Only display file "full" names['root_dir\\file0','root_dir\\file1']
O link da documentação é do ActiveState , pois não encontrei nenhuma documentação oficial do PyWin32
Instale algum (outro) pacote de terceiros que faça o truque
Provavelmente, dependerá de um (ou mais) dos itens acima (talvez com pequenas personalizações)
Notas :
O código deve ser portátil (exceto locais direcionados a uma área específica - que estão marcadas) ou cruzado:
plataforma ( Nix , Win ,)
PitãoVersão (2, 3,)
Vários estilos de caminho (absoluto, parentes) foram usados nas variantes acima, para ilustrar o fato de que as "ferramentas" usadas são flexíveis nessa direção
_get_dir_content (do ponto 1 ) pode ser implementado usando qualquer uma dessas abordagens (algumas exigirão mais trabalho e outras menos)
Alguma filtragem avançada (em vez de apenas arquivo x diretório) poderia ser feita: por exemplo, o argumento include_folders poderia ser substituído por outro (por exemplo, filter_func ), que seria uma função que seguiria o caminho como argumento: filter_func=lambda x: True(isso não desaparece qualquer coisa) e dentro de _get_dir_content algo como: if not filter_func(entry_with_path): continue(se a função falhar em uma entrada, ela será ignorada), mas quanto mais complexo o código se tornar, mais tempo será necessário para executar
Nota bene! Como a recursão é usada, devo mencionar que fiz alguns testes no meu laptop ( Win 10 x64 ), totalmente não relacionados a esse problema, e quando o nível de recursão estava atingindo valores em algum lugar na faixa ( 990 .. 1000) ( recursionlimit - 1000 (padrão)), recebi o StackOverflow :). Se a árvore de diretórios exceder esse limite (não sou especialista em FS , não sei se isso é possível), isso pode ser um problema.
Devo também mencionar que não tentei aumentar o limite de recursão porque não tenho experiência na área (quanto posso aumentá-lo antes de aumentar também a pilha no SOnível), mas em teoria sempre haverá a possibilidade de falha, se a profundidade do diretório for maior que o limite de recursão mais alto possível (nessa máquina)
As amostras de código são apenas para fins demonstrativos. Isso significa que eu não levei em consideração o tratamento de erros (acho que não há nenhum bloco try / except / else / finalmente ), portanto o código não é robusto (o motivo é: mantê-lo o mais simples e curto possível ) Para a produção , o tratamento de erros também deve ser adicionado
Outras abordagens:
Use Python apenas como um wrapper
Tudo é feito usando outra tecnologia
Essa tecnologia é invocada no Python
O sabor mais famoso que conheço é o que chamo de abordagem de administrador do sistema :
Use Python (ou qualquer outra linguagem de programação) para executar comandos do shell (e analisar suas saídas)
Alguns consideram isso um hack puro
Eu considero isso mais como uma solução alternativa esfarrapada ( gainarie ), pois a ação em si é executada a partir do shell ( cmd neste caso) e, portanto, não tem nada a ver com Python .
A filtragem ( grep/ findstr) ou a formatação de saída pode ser feita nos dois lados, mas não vou insistir nisso. Além disso, eu usei deliberadamente em os.systemvez de subprocess.Popen.
Em geral, essa abordagem deve ser evitada, pois se algum formato de saída de comando diferir ligeiramente entre versões / tipos de SO , o código de análise também deverá ser adaptado; para não mencionar diferenças entre localidades).
Gostei muito da resposta de adamk , sugerindo que você use glob(), do módulo com o mesmo nome. Isso permite que você tenha correspondência de padrões com *s.
Mas, como outras pessoas apontaram nos comentários, glob()podem ser enganados por direções inconsistentes de barras. Para ajudar nisso, sugiro que você use as funções join()e expanduser()no os.pathmódulo, e talvez a getcwd()função no osmódulo também.
Como exemplos:
from glob import glob
# Return everything under C:\Users\admin that contains a folder called wlp.
glob('C:\Users\admin\*\wlp')
O que foi dito acima é terrível - o caminho foi codificado e só funcionará no Windows entre o nome da unidade e os \códigos codificados no caminho.
from glob import glob
from os.path import join
# Return everything under Users, admin, that contains a folder called wlp.
glob(join('Users','admin','*','wlp'))
O exemplo acima funciona melhor, mas depende do nome da pasta, Usersque geralmente é encontrada no Windows e não é encontrada em outros sistemas operacionais. Também depende do usuário ter um nome específico admin,.
from glob import glob
from os.path import expanduser, join
# Return everything under the user directory that contains a folder called wlp.
glob(join(expanduser('~'),'*','wlp'))
Isso funciona perfeitamente em todas as plataformas.
Outro ótimo exemplo que funciona perfeitamente entre plataformas e faz algo um pouco diferente:
from glob import glob
from os import getcwd
from os.path import join
# Return everything under the current directory that contains a folder called wlp.
glob(join(getcwd(),'*','wlp'))
Espero que esses exemplos o ajudem a ver o poder de algumas das funções que você pode encontrar nos módulos padrão da biblioteca Python.
def list_files(path):# returns a list of names (with extension, without full path) of all files # in folder path
files =[]for name in os.listdir(path):if os.path.isfile(os.path.join(path, name)):
files.append(name)return files
Para obter melhores resultados, você pode usar o listdir()métodoos módulo junto com um gerador (um gerador é um iterador poderoso que mantém seu estado, lembra?). O código a seguir funciona bem com as duas versões: Python 2 e Python 3.
Aqui está um código:
import os
def files(path):for file in os.listdir(path):if os.path.isfile(os.path.join(path, file)):yield file
for file in files("."):print(file)
O listdir()método retorna a lista de entradas para o diretório especificado. O método os.path.isfile()retornará Truese a entrada fornecida for um arquivo. E o yieldoperador sai da função, mas mantém seu estado atual e retorna apenas o nome da entrada detectada como um arquivo. Todos os itens acima nos permitem fazer um loop sobre a função do gerador.
Nota: os.path.abspath(f)seria um substituto um pouco mais barato os.path.join(os.getcwd(),f).
ShadowRanger
Eu seria mais eficiente ainda se você começasse cwd = os.path.abspath('.')e depois usasse em cwdvez de '.'e os.getcwd()para evitar cargas de chamadas de sistema redundantes.
O mesmo pode ser alcançado em apenas uma linha com pathlib:filter(Path.is_file, Path().rglob('*'))
Georgy
9
Um professor sábio me disse uma vez que:
Quando existem várias maneiras estabelecidas de fazer algo, nenhuma delas é boa para todos os casos.
Assim, adicionarei uma solução para um subconjunto do problema: muitas vezes, queremos apenas verificar se um arquivo corresponde a uma sequência inicial e uma final, sem entrar em subdiretórios. Assim, gostaríamos de uma função que retorne uma lista de nomes de arquivos, como:
Se você deseja primeiro declarar duas funções, isso pode ser feito:
def file_filter(filename, radical='', extension=''):"Check if a filename matches a radical and extension"ifnot filename:returnFalse
filename = filename.strip()return(filename.startswith(radical)and filename.endswith(extension))def dir_filter(dirname='', radical='', extension=''):"Filter filenames in directory according to radical and extension"ifnot dirname:
dirname ='.'return[filename for filename in os.listdir(dirname)if file_filter(filename, radical, extension)]
Essa solução pode ser facilmente generalizada com expressões regulares (e você pode adicionar um patternargumento, se não desejar que seus padrões sempre atinjam o início ou o final do nome do arquivo).
Outra variante muito legível para o Python 3.4+ está usando pathlib.Path.glob:
from pathlib importPath
folder ='/foo'[f for f inPath(folder).glob('*')if f.is_file()]
É simples tornar mais específico, por exemplo, procure apenas arquivos de origem Python que não são links simbólicos, também em todos os subdiretórios:
[f for f inPath(folder).glob('**/*.py')ifnot f.is_symlink()]
Aqui está minha função de propósito geral para isso. Ele retorna uma lista de caminhos de arquivos, em vez de nomes de arquivos, desde que achei mais útil. Ele possui alguns argumentos opcionais que o tornam versátil. Por exemplo, costumo usá-lo com argumentos como pattern='*.txt'ou subfolders=True.
import os
import fnmatch
def list_paths(folder='.', pattern='*', case_sensitive=False, subfolders=False):"""Return a list of the file paths matching the pattern in the specified
folder, optionally including files inside subfolders.
"""
match = fnmatch.fnmatchcase if case_sensitive else fnmatch.fnmatch
walked = os.walk(folder)if subfolders else[next(os.walk(folder))]return[os.path.join(root, f)for root, dirnames, filenames in walked
for f in filenames if match(f, pattern)]
Fornecerei uma amostra de um liner em que o caminho de origem e o tipo de arquivo possam ser fornecidos como entrada. O código retorna uma lista de nomes de arquivos com extensão csv. Use . caso todos os arquivos precisem ser retornados. Isso também verifica recursivamente os subdiretórios.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
Modifique as extensões de arquivo e o caminho de origem, conforme necessário.
Se você for usar glob, basta usar glob('**/*.csv', recursive=True). Não é necessário combinar isso com o os.walk()recursivo ( recursivee **são suportados desde o Python 3.5).
Respostas:
os.listdir()
você terá tudo o que está em um diretório - arquivos e diretórios .Se você quiser apenas arquivos, poderá filtrar isso usando
os.path
:ou você pode usar o
os.walk()
que produzirá duas listas para cada diretório visitado - dividindo-se em arquivos e diretórios para você. Se você deseja apenas o diretório superior, basta interromper a primeira vez que ele produzirfonte
(_, _, filenames) = walk(mypath).next()
(se você está confiante de que a caminhada irá retornar pelo menos um valor, que deveria.)f.extend(filenames)
não é realmente equivalente af = f + filenames
.extend
será modificadof
no local, enquanto a adição cria uma nova lista em um novo local de memória. Isso significa queextend
geralmente é mais eficiente que+
, mas às vezes pode causar confusão se vários objetos mantiverem referências à lista. Por fim, vale a pena notar que issof += filenames
é equivalente af.extend(filenames)
, nãof = f + filenames
._, _, filenames = next(walk(mypath), (None, None, []))
(_, _, filenames) = next(os.walk(mypath))
Eu prefiro usar o
glob
módulo, pois combina correspondência e expansão de padrões.Ele retornará uma lista com os arquivos consultados:
fonte
/home/user/foo/bar/hello.txt
, se estiver sendo executado no diretóriofoo
, o valorglob("bar/*.txt")
retornarábar/hello.txt
. Há casos em que você realmente deseja o caminho completo (ou seja, absoluto); para esses casos, consulte stackoverflow.com/questions/51520/…glob.glob("*")
seria.x=glob.glob("../train/*.png")
me dará uma matriz dos meus caminhos, desde que eu saiba o nome da pasta. Tão legal!Como obter todos os arquivos (e diretórios) no diretório atual (Python 3)
A seguir, são métodos simples para recuperar apenas arquivos no diretório atual, usando
os
e alistdir()
função, no Python 3. Explorações adicionais demonstrarão como retornar pastas no diretório, mas você não terá o arquivo no subdiretório, para o qual você pode usar o walk - discutido mais tarde).Achei a glob mais fácil de selecionar o arquivo do mesmo tipo ou com algo em comum. Veja o seguinte exemplo:
A função retorna uma lista da extensão fornecida (.txt, .docx ecc.) No argumento
A função agora retorna uma lista de arquivos que correspondem à string que você passa como argumento
resultado
Como você notou, você não tem o caminho completo do arquivo no código acima. Se você precisar ter o caminho absoluto, poderá usar outra função do
os.path
módulo chamada_getfullpathname
, colocando o arquivo que obtémos.listdir()
como argumento. Existem outras maneiras de ter o caminho completo, como verificaremos mais tarde (substituí, como sugerido por mexmex, _getfullpathname withabspath
).Acho isso muito útil para encontrar coisas em muitos diretórios e me ajudou a encontrar um arquivo sobre o qual não me lembrava do nome:
No Python 2, se você quiser a lista dos arquivos no diretório atual, precisará fornecer o argumento como '.' ou os.getcwd () no método os.listdir.
Se eu precisar do caminho absoluto dos arquivos:
Com
list comprehension
:Como alternativa, use em
pathlib.Path()
vez depathlib.Path(".")
Neste exemplo, procuramos o número de arquivos incluídos em todo o diretório e seus subdiretórios.
Um script para fazer o pedido em seu computador, localizando todos os arquivos de um tipo (padrão: pptx) e copiando-os em uma nova pasta.
Caso você queira criar um arquivo txt com todos os nomes de arquivos:
Com esta função, você pode criar um arquivo txt que terá o nome de um tipo de arquivo que você procura (por exemplo, pngfile.txt) com todo o caminho completo de todos os arquivos desse tipo. Às vezes, pode ser útil, eu acho.
fonte
retornará uma lista de todos os arquivos e diretórios no "somedirectory".
fonte
glob.glob
os.listdir()
sempre retorna meros nomes de arquivos (não caminhos relativos). Oglob.glob()
retorno é conduzido pelo formato do caminho do padrão de entrada.Uma solução de uma linha para obter apenas a lista de arquivos (sem subdiretórios):
ou caminhos absolutos:
fonte
import os
. Parece menos conciso do queglob()
para mim.glob()
o trataria como um arquivo. Seu método o trataria como um diretório.Obtendo caminhos de arquivo completos de um diretório e de todos os seus subdiretórios
print full_file_paths
que imprimirá a lista:['/Users/johnny/Desktop/TEST/file1.txt', '/Users/johnny/Desktop/TEST/file2.txt', '/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat']
Se desejar, você pode abrir e ler o conteúdo ou se concentrar apenas em arquivos com a extensão ".dat", como no código abaixo:
/Users/johnny/Desktop/TEST/SUBFOLDER/file3.dat
fonte
Desde a versão 3.4, existem iteradores internos para isso, que são muito mais eficientes do que
os.listdir()
:pathlib
: Novo na versão 3.4.De acordo com o PEP 428 , o objetivo da
pathlib
biblioteca é fornecer uma hierarquia simples de classes para manipular os caminhos do sistema de arquivos e as operações comuns que os usuários fazem sobre eles.os.scandir()
: Novo na versão 3.5.Observe que
os.walk()
usa emos.scandir()
vez daos.listdir()
versão 3.5 e sua velocidade aumentou de 2 a 20 vezes, de acordo com o PEP 471 .Deixe-me também recomendar a leitura do comentário de ShadowRanger abaixo.
fonte
list
. Poderia usar emp.name
vez do primeirop
alternativamente, se preferir.pathlib.Path()
instâncias, pois eles têm muitos métodos úteis que eu não gostaria de desperdiçar. Você também pode chamástr(p)
-los para nomes de caminhos.os.scandir
solução será mais eficiente do queos.listdir
com umaos.path.is_file
verificação ou algo parecido, mesmo se você precisar de umalist
(para que você não se beneficie da iteração lenta), porqueos.scandir
usa APIs fornecidas pelo SO que fornecemis_file
informações gratuitamente enquanto itera , não por arquivo de ida e volta para o disco parastat
eles em tudo (no Windows, osDirEntry
s te completastat
informações de graça, em sistemas * NIX ele precisastat
de informações para alémis_file
,is_dir
etc., masDirEntry
caches na primeirastat
por conveniência).entry.name
para obter apenas o nome do arquivo ouentry.path
para obter o caminho completo. Não há mais os.path.join () em todo o lugar.Notas preliminares
Quando a pergunta foi feita, imagino que o Python 2 fosse a versão LTS , no entanto, os exemplos de código serão executados pelo Python 3 ( .5 ) (eu os manterei o mais compatível possível com o Python 2 ; também, qualquer código pertencente a O Python que vou postar é da v3.5.4 - a menos que seja especificado de outra forma). Isso tem consequências relacionadas a outra palavra-chave na pergunta: " adicione-as a uma lista ":
Os exemplos serão baseados em um diretório chamado root_dir com a seguinte estrutura (este exemplo é para Win , mas também estou usando a mesma árvore no Lnx ):
Soluções
Abordagens programáticas:
[Python 3]: os. listdir ( caminho = '.' )
Um exemplo mais elaborado ( code_os_listdir.py ):
Notas :
Saída :
[Python 3]: os. scandir ( caminho = '.' ) ( Python 3.5 +, backport: [PyPI]: scandir )
Notas :
os.listdir
[Python 3]: os. walk ( top, topdown = True, onerror = None, followlinks = False )
Notas :
os.scandir
(os.listdir
em versões mais antigas)[Python 3]: glob. glob ( nome do caminho, *, recursivo = Falso ) ( [Python 3]: glob. iglob ( nome do caminho, *, recursivo = Falso ) )
Notas :
os.listdir
[Python 3]: classe pathlib. Caminho ( * pathegments ) ( Python 3.4 +, backport: [PyPI]: pathlib2 )
Notas :
[Python 2]: dircache.listdir (caminho) ( somente Python 2 )
os.listdir
com o cache[man7]: OPENDIR (3) / [man7]: READDIR (3) / [man7]: CLOSEDIR (3) via [Python 3]: ctypes - Uma biblioteca de funções estrangeira para Python ( específico para POSIX )
code_ctypes.py :
Notas :
os.walk
formato do. Eu não me incomodei em torná-lo recursivo, mas a partir do código existente, isso seria uma tarefa bastante trivialSaída :
[ActiveState.Docs]: win32file.FindFilesW ( específico para Win )
Notas :
win32file.FindFilesW
faz parte do [GitHub]: mhammond / pywin32 - Extensões do Python para Windows (pywin32) , que é um wrapper Python sobre o WINAPI sNotas :
O código deve ser portátil (exceto locais direcionados a uma área específica - que estão marcadas) ou cruzado:
Vários estilos de caminho (absoluto, parentes) foram usados nas variantes acima, para ilustrar o fato de que as "ferramentas" usadas são flexíveis nessa direção
os.listdir
eos.scandir
use opendir / readdir / closedir ( [MS.Docs]: função FindFirstFileW / [MS.Docs]: função FindNextFileW / [MS.Docs]: função FindClose ) (via [GitHub]: python / cpython - (master) cpython / Módulos / posixmodule.c )win32file.FindFilesW
também usa essas funções ( específicas do Win ) (via [GitHub]: mhammond / pywin32 - (mestre) pywin32 / win32 / src / win32file.i )_get_dir_content (do ponto 1 ) pode ser implementado usando qualquer uma dessas abordagens (algumas exigirão mais trabalho e outras menos)
filter_func=lambda x: True
(isso não desaparece qualquer coisa) e dentro de _get_dir_content algo como:if not filter_func(entry_with_path): continue
(se a função falhar em uma entrada, ela será ignorada), mas quanto mais complexo o código se tornar, mais tempo será necessário para executarNota bene! Como a recursão é usada, devo mencionar que fiz alguns testes no meu laptop ( Win 10 x64 ), totalmente não relacionados a esse problema, e quando o nível de recursão estava atingindo valores em algum lugar na faixa ( 990 .. 1000) ( recursionlimit - 1000 (padrão)), recebi o StackOverflow :). Se a árvore de diretórios exceder esse limite (não sou especialista em FS , não sei se isso é possível), isso pode ser um problema.
Devo também mencionar que não tentei aumentar o limite de recursão porque não tenho experiência na área (quanto posso aumentá-lo antes de aumentar também a pilha no SOnível), mas em teoria sempre haverá a possibilidade de falha, se a profundidade do diretório for maior que o limite de recursão mais alto possível (nessa máquina)
As amostras de código são apenas para fins demonstrativos. Isso significa que eu não levei em consideração o tratamento de erros (acho que não há nenhum bloco try / except / else / finalmente ), portanto o código não é robusto (o motivo é: mantê-lo o mais simples e curto possível ) Para a produção , o tratamento de erros também deve ser adicionado
Outras abordagens:
Use Python apenas como um wrapper
O sabor mais famoso que conheço é o que chamo de abordagem de administrador do sistema :
grep
/findstr
) ou a formatação de saída pode ser feita nos dois lados, mas não vou insistir nisso. Além disso, eu usei deliberadamente emos.system
vez desubprocess.Popen
.Em geral, essa abordagem deve ser evitada, pois se algum formato de saída de comando diferir ligeiramente entre versões / tipos de SO , o código de análise também deverá ser adaptado; para não mencionar diferenças entre localidades).
fonte
Gostei muito da resposta de adamk , sugerindo que você use
glob()
, do módulo com o mesmo nome. Isso permite que você tenha correspondência de padrões com*
s.Mas, como outras pessoas apontaram nos comentários,
glob()
podem ser enganados por direções inconsistentes de barras. Para ajudar nisso, sugiro que você use as funçõesjoin()
eexpanduser()
noos.path
módulo, e talvez agetcwd()
função noos
módulo também.Como exemplos:
O que foi dito acima é terrível - o caminho foi codificado e só funcionará no Windows entre o nome da unidade e os
\
códigos codificados no caminho.O exemplo acima funciona melhor, mas depende do nome da pasta,
Users
que geralmente é encontrada no Windows e não é encontrada em outros sistemas operacionais. Também depende do usuário ter um nome específicoadmin
,.Isso funciona perfeitamente em todas as plataformas.
Outro ótimo exemplo que funciona perfeitamente entre plataformas e faz algo um pouco diferente:
Espero que esses exemplos o ajudem a ver o poder de algumas das funções que você pode encontrar nos módulos padrão da biblioteca Python.
fonte
**
funciona enquanto você definirrecursive = True
. Veja os documentos aqui: docs.python.org/3.5/library/glob.html#glob.globfonte
Se você está procurando uma implementação Python de find , esta é uma receita que eu uso com bastante frequência:
Então criei um pacote PyPI e também há um repositório GitHub . Espero que alguém ache isso potencialmente útil para esse código.
fonte
Para obter melhores resultados, você pode usar o
listdir()
métodoos
módulo junto com um gerador (um gerador é um iterador poderoso que mantém seu estado, lembra?). O código a seguir funciona bem com as duas versões: Python 2 e Python 3.Aqui está um código:
O
listdir()
método retorna a lista de entradas para o diretório especificado. O métodoos.path.isfile()
retornaráTrue
se a entrada fornecida for um arquivo. E oyield
operador sai da função, mas mantém seu estado atual e retorna apenas o nome da entrada detectada como um arquivo. Todos os itens acima nos permitem fazer um loop sobre a função do gerador.fonte
O retorno de uma lista de caminhos de arquivo absolutos não recursa em subdiretórios
fonte
os.path.abspath(f)
seria um substituto um pouco mais baratoos.path.join(os.getcwd(),f)
.cwd = os.path.abspath('.')
e depois usasse emcwd
vez de'.'
eos.getcwd()
para evitar cargas de chamadas de sistema redundantes.Aqui eu uso uma estrutura recursiva.
fonte
pathlib
:filter(Path.is_file, Path().rglob('*'))
Um professor sábio me disse uma vez que:
Assim, adicionarei uma solução para um subconjunto do problema: muitas vezes, queremos apenas verificar se um arquivo corresponde a uma sequência inicial e uma final, sem entrar em subdiretórios. Assim, gostaríamos de uma função que retorne uma lista de nomes de arquivos, como:
Se você deseja primeiro declarar duas funções, isso pode ser feito:
Essa solução pode ser facilmente generalizada com expressões regulares (e você pode adicionar um
pattern
argumento, se não desejar que seus padrões sempre atinjam o início ou o final do nome do arquivo).fonte
Usando geradores
fonte
Outra variante muito legível para o Python 3.4+ está usando pathlib.Path.glob:
É simples tornar mais específico, por exemplo, procure apenas arquivos de origem Python que não são links simbólicos, também em todos os subdiretórios:
fonte
Aqui está minha função de propósito geral para isso. Ele retorna uma lista de caminhos de arquivos, em vez de nomes de arquivos, desde que achei mais útil. Ele possui alguns argumentos opcionais que o tornam versátil. Por exemplo, costumo usá-lo com argumentos como
pattern='*.txt'
ousubfolders=True
.fonte
Fornecerei uma amostra de um liner em que o caminho de origem e o tipo de arquivo possam ser fornecidos como entrada. O código retorna uma lista de nomes de arquivos com extensão csv. Use . caso todos os arquivos precisem ser retornados. Isso também verifica recursivamente os subdiretórios.
[y for x in os.walk(sourcePath) for y in glob(os.path.join(x[0], '*.csv'))]
Modifique as extensões de arquivo e o caminho de origem, conforme necessário.
fonte
glob
, basta usarglob('**/*.csv', recursive=True)
. Não é necessário combinar isso com oos.walk()
recursivo (recursive
e**
são suportados desde o Python 3.5).Para python2: pip install rglob
fonte
dircache é " Descontinuado desde a versão 2.6: O módulo dircache foi removido no Python 3.0."
fonte