Respostas:
Você pode usar glob
:
import glob, os
os.chdir("/mydir")
for file in glob.glob("*.txt"):
print(file)
ou simplesmente os.listdir
:
import os
for file in os.listdir("/mydir"):
if file.endswith(".txt"):
print(os.path.join("/mydir", file))
ou se você quiser atravessar o diretório, use os.walk
:
import os
for root, dirs, files in os.walk("/mydir"):
for file in files:
if file.endswith(".txt"):
print(os.path.join(root, file))
for file in f
que para, for files in f
uma vez que o que está na variável é um único nome de arquivo. Melhor ainda seria mudar os f
to files
e então os loops for poderiam se tornar for file in files
.
file
não é uma palavra reservada, apenas o nome de uma função predefinida, por isso é bem possível usá-la como um nome de variável em seu próprio código. Embora seja verdade que geralmente se deve evitar colisões como essa, file
é um caso especial, porque quase nunca há necessidade de usá-lo, por isso é frequentemente considerado uma exceção à diretriz. Se você não quiser fazer isso, o PEP8 recomenda anexar um único sublinhado a esses nomes, ou seja file_
, o que você teria que concordar que ainda é bastante legível.
Use glob .
>>> import glob
>>> glob.glob('./*.txt')
['./outline.txt', './pip-log.txt', './test.txt', './testingvim.txt']
glob
para não encontrar arquivos recursivamente se o seu python estiver abaixo de 3,5. mais informada
Algo assim deve fazer o trabalho
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith('.txt'):
print file
root, dirs, files
vez de r, d, f
. Muito mais legível.
Algo assim vai funcionar:
>>> import os
>>> path = '/usr/share/cups/charmaps'
>>> text_files = [f for f in os.listdir(path) if f.endswith('.txt')]
>>> text_files
['euc-cn.txt', 'euc-jp.txt', 'euc-kr.txt', 'euc-tw.txt', ... 'windows-950.txt']
os.path.join
em cada elemento de text_files
. Pode ser algo parecido text_files = [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.txt')]
.
Você pode simplesmente usar pathlib
s 1 :glob
import pathlib
list(pathlib.Path('your_directory').glob('*.txt'))
ou em um loop:
for txt_file in pathlib.Path('your_directory').glob('*.txt'):
# do something with "txt_file"
Se você quiser recursivo, você pode usar .glob('**/*.txt)
1 O pathlib
módulo foi incluído na biblioteca padrão no python 3.4. Mas você pode instalar portas traseiras desse módulo, mesmo em versões mais antigas do Python (ou seja, usando conda
or pip
): pathlib
e pathlib2
.
**/*.txt
não é suportado pelo python mais velho versions.So Eu resolvi isso com: foundfiles= subprocess.check_output("ls **/*.txt", shell=True)
for foundfile in foundfiles.splitlines():
print foundfile
pathlib
posso fazer e eu já incluí os requisitos de versão do Python. :) Mas se sua abordagem ainda não foi publicada, por que não adicioná-la como outra resposta?
rglob
se desejar procurar itens recursivamente. Por exemplo.rglob('*.txt')
import os
path = 'mypath/path'
files = os.listdir(path)
files_txt = [i for i in files if i.endswith('.txt')]
Eu gosto do os.walk () :
import os
for root, dirs, files in os.walk(dir):
for f in files:
if os.path.splitext(f)[1] == '.txt':
fullpath = os.path.join(root, f)
print(fullpath)
Ou com geradores:
import os
fileiter = (os.path.join(root, f)
for root, _, files in os.walk(dir)
for f in files)
txtfileiter = (f for f in fileiter if os.path.splitext(f)[1] == '.txt')
for txt in txtfileiter:
print(txt)
Aqui estão mais versões do mesmo que produzem resultados ligeiramente diferentes:
import glob
for f in glob.iglob("/mydir/*/*.txt"): # generator, search immediate subdirectories
print f
print glob.glob1("/mydir", "*.tx?") # literal_directory, basename_pattern
import fnmatch, os
print fnmatch.filter(os.listdir("/mydir"), "*.tx?") # include dot-files
glob1()
é uma função auxiliar no glob
módulo que não está listada na documentação do Python. Existem alguns comentários embutidos descrevendo o que ele faz no arquivo de origem, consulte .../Lib/glob.py
.
glob.glob1()
não é público, mas está disponível no Python 2.4-2.7; 3.0-3.2; pypy; jython github.com/zed/test_glob1
glob
módulo.
path.py é outra alternativa: https://github.com/jaraco/path.py
from path import path
p = path('/path/to/the/directory')
for f in p.files(pattern='*.txt'):
print f
for f in p.walk(pattern='*.txt')
passar por cada subpastas
list(p.glob('**/*.py'))
Método rápido usando os.scandir em uma função recursiva. Pesquisa todos os arquivos com uma extensão especificada na pasta e nas subpastas.
import os
def findFilesInFolder(path, pathList, extension, subFolders = True):
""" Recursive function to find all files of an extension type in a folder (and optionally in all subfolders too)
path: Base directory to find files
pathList: A list that stores all paths
extension: File extension to find
subFolders: Bool. If True, find files in all subfolders under path. If False, only searches files in the specified folder
"""
try: # Trapping a OSError: File permissions problem I believe
for entry in os.scandir(path):
if entry.is_file() and entry.path.endswith(extension):
pathList.append(entry.path)
elif entry.is_dir() and subFolders: # if its a directory, then repeat process as a nested function
pathList = findFilesInFolder(entry.path, pathList, extension, subFolders)
except OSError:
print('Cannot access ' + path +'. Probably a permissions error')
return pathList
dir_name = r'J:\myDirectory'
extension = ".txt"
pathList = []
pathList = findFilesInFolder(dir_name, pathList, extension, True)
Se você estiver pesquisando em diretórios que contêm arquivos de 10.000, anexar a uma lista se tornará ineficiente. 'Produzir' os resultados é uma solução melhor. Também incluí uma função para converter a saída em um Dataframe do Pandas.
import os
import re
import pandas as pd
import numpy as np
def findFilesInFolderYield(path, extension, containsTxt='', subFolders = True, excludeText = ''):
""" Recursive function to find all files of an extension type in a folder (and optionally in all subfolders too)
path: Base directory to find files
extension: File extension to find. e.g. 'txt'. Regular expression. Or 'ls\d' to match ls1, ls2, ls3 etc
containsTxt: List of Strings, only finds file if it contains this text. Ignore if '' (or blank)
subFolders: Bool. If True, find files in all subfolders under path. If False, only searches files in the specified folder
excludeText: Text string. Ignore if ''. Will exclude if text string is in path.
"""
if type(containsTxt) == str: # if a string and not in a list
containsTxt = [containsTxt]
myregexobj = re.compile('\.' + extension + '$') # Makes sure the file extension is at the end and is preceded by a .
try: # Trapping a OSError or FileNotFoundError: File permissions problem I believe
for entry in os.scandir(path):
if entry.is_file() and myregexobj.search(entry.path): #
bools = [True for txt in containsTxt if txt in entry.path and (excludeText == '' or excludeText not in entry.path)]
if len(bools)== len(containsTxt):
yield entry.stat().st_size, entry.stat().st_atime_ns, entry.stat().st_mtime_ns, entry.stat().st_ctime_ns, entry.path
elif entry.is_dir() and subFolders: # if its a directory, then repeat process as a nested function
yield from findFilesInFolderYield(entry.path, extension, containsTxt, subFolders)
except OSError as ose:
print('Cannot access ' + path +'. Probably a permissions error ', ose)
except FileNotFoundError as fnf:
print(path +' not found ', fnf)
def findFilesInFolderYieldandGetDf(path, extension, containsTxt, subFolders = True, excludeText = ''):
""" Converts returned data from findFilesInFolderYield and creates and Pandas Dataframe.
Recursive function to find all files of an extension type in a folder (and optionally in all subfolders too)
path: Base directory to find files
extension: File extension to find. e.g. 'txt'. Regular expression. Or 'ls\d' to match ls1, ls2, ls3 etc
containsTxt: List of Strings, only finds file if it contains this text. Ignore if '' (or blank)
subFolders: Bool. If True, find files in all subfolders under path. If False, only searches files in the specified folder
excludeText: Text string. Ignore if ''. Will exclude if text string is in path.
"""
fileSizes, accessTimes, modificationTimes, creationTimes , paths = zip(*findFilesInFolderYield(path, extension, containsTxt, subFolders))
df = pd.DataFrame({
'FLS_File_Size':fileSizes,
'FLS_File_Access_Date':accessTimes,
'FLS_File_Modification_Date':np.array(modificationTimes).astype('timedelta64[ns]'),
'FLS_File_Creation_Date':creationTimes,
'FLS_File_PathName':paths,
})
df['FLS_File_Modification_Date'] = pd.to_datetime(df['FLS_File_Modification_Date'],infer_datetime_format=True)
df['FLS_File_Creation_Date'] = pd.to_datetime(df['FLS_File_Creation_Date'],infer_datetime_format=True)
df['FLS_File_Access_Date'] = pd.to_datetime(df['FLS_File_Access_Date'],infer_datetime_format=True)
return df
ext = 'txt' # regular expression
containsTxt=[]
path = 'C:\myFolder'
df = findFilesInFolderYieldandGetDf(path, ext, containsTxt, subFolders = True)
Python tem todas as ferramentas para fazer isso:
import os
the_dir = 'the_dir_that_want_to_search_in'
all_txt_files = filter(lambda x: x.endswith('.txt'), os.listdir(the_dir))
all_txt_files = list(filter(lambda x: x.endswith('.txt'), os.listdir(the_dir)))
Para obter todos os nomes de arquivos '.txt' dentro da pasta 'dataPath' como uma lista de maneira Pythonic:
from os import listdir
from os.path import isfile, join
path = "/dataPath/"
onlyTxtFiles = [f for f in listdir(path) if isfile(join(path, f)) and f.endswith(".txt")]
print onlyTxtFiles
Tente isso, ele encontrará todos os seus arquivos recursivamente:
import glob, os
os.chdir("H:\\wallpaper")# use whatever directory you want
#double\\ no single \
for file in glob.glob("**/*.txt", recursive = True):
print(file)
**
. Disponível apenas em python 3. O que eu não gosto é a chdir
parte. Não é preciso isso.
filepath = os.path.join('wallpaper')
e depois usá-lo como glob.glob(filepath+"**/*.psd", recursive = True)
, o que produziria o mesmo resultado.
Fiz um teste (Python 3.6.4, W7x64) para ver qual solução é a mais rápida para uma pasta, sem subdiretórios, para obter uma lista dos caminhos completos dos arquivos com uma extensão específica.
Para resumir, essa tarefa os.listdir()
é a mais rápida e é 1,7x mais rápida que a seguinte: os.walk()
(com uma folga!), 2,7x mais rápida que pathlib
, 3,2x mais rápida os.scandir()
e 3,3x mais rápida glob
.
Lembre-se de que esses resultados serão alterados quando você precisar de resultados recursivos. Se você copiar / colar um método abaixo, adicione um .lower (), caso contrário .EXT não seria encontrado ao pesquisar .ext.
import os
import pathlib
import timeit
import glob
def a():
path = pathlib.Path().cwd()
list_sqlite_files = [str(f) for f in path.glob("*.sqlite")]
def b():
path = os.getcwd()
list_sqlite_files = [f.path for f in os.scandir(path) if os.path.splitext(f)[1] == ".sqlite"]
def c():
path = os.getcwd()
list_sqlite_files = [os.path.join(path, f) for f in os.listdir(path) if f.endswith(".sqlite")]
def d():
path = os.getcwd()
os.chdir(path)
list_sqlite_files = [os.path.join(path, f) for f in glob.glob("*.sqlite")]
def e():
path = os.getcwd()
list_sqlite_files = [os.path.join(path, f) for f in glob.glob1(str(path), "*.sqlite")]
def f():
path = os.getcwd()
list_sqlite_files = []
for root, dirs, files in os.walk(path):
for file in files:
if file.endswith(".sqlite"):
list_sqlite_files.append( os.path.join(root, file) )
break
print(timeit.timeit(a, number=1000))
print(timeit.timeit(b, number=1000))
print(timeit.timeit(c, number=1000))
print(timeit.timeit(d, number=1000))
print(timeit.timeit(e, number=1000))
print(timeit.timeit(f, number=1000))
Resultados:
# Python 3.6.4
0.431
0.515
0.161
0.548
0.537
0.274
Este código torna minha vida mais simples.
import os
fnames = ([file for root, dirs, files in os.walk(dir)
for file in files
if file.endswith('.txt') #or file.endswith('.png') or file.endswith('.pdf')
])
for fname in fnames: print(fname)
Use fnmatch: https://docs.python.org/2/library/fnmatch.html
import fnmatch
import os
for file in os.listdir('.'):
if fnmatch.fnmatch(file, '*.txt'):
print file
Para obter uma matriz de nomes de arquivo ".txt" de uma pasta chamada "data" no mesmo diretório, costumo usar esta simples linha de código:
import os
fileNames = [fileName for fileName in os.listdir("data") if fileName.endswith(".txt")]
Eu sugiro que você use fnmatch e o método superior. Dessa forma, você pode encontrar um dos seguintes:
.
import fnmatch
import os
for file in os.listdir("/Users/Johnny/Desktop/MyTXTfolder"):
if fnmatch.fnmatch(file.upper(), '*.TXT'):
print(file)
Solução funcional com subdiretórios:
from fnmatch import filter
from functools import partial
from itertools import chain
from os import path, walk
print(*chain(*(map(partial(path.join, root), filter(filenames, "*.txt")) for root, _, filenames in walk("mydir"))))
Caso a pasta contenha muitos arquivos ou a memória seja uma restrição, considere o uso de geradores:
def yield_files_with_extensions(folder_path, file_extension):
for _, _, files in os.walk(folder_path):
for file in files:
if file.endswith(file_extension):
yield file
Opção A: Iterar
for f in yield_files_with_extensions('.', '.txt'):
print(f)
Opção B: obter todos
files = [f for f in yield_files_with_extensions('.', '.txt')]
Uma solução para copiar e colar, semelhante à do ghostdog:
def get_all_filepaths(root_path, ext):
"""
Search all files which have a given extension within root_path.
This ignores the case of the extension and searches subdirectories, too.
Parameters
----------
root_path : str
ext : str
Returns
-------
list of str
Examples
--------
>>> get_all_filepaths('/run', '.lock')
['/run/unattended-upgrades.lock',
'/run/mlocate.daily.lock',
'/run/xtables.lock',
'/run/mysqld/mysqld.sock.lock',
'/run/postgresql/.s.PGSQL.5432.lock',
'/run/network/.ifstate.lock',
'/run/lock/asound.state.lock']
"""
import os
all_files = []
for root, dirs, files in os.walk(root_path):
for filename in files:
if filename.lower().endswith(ext):
all_files.append(os.path.join(root, filename))
return all_files
use o módulo Python OS para encontrar arquivos com extensão específica.
o exemplo simples está aqui:
import os
# This is the path where you want to search
path = r'd:'
# this is extension you want to detect
extension = '.txt' # this can be : .jpg .png .xls .log .....
for root, dirs_list, files_list in os.walk(path):
for file_name in files_list:
if os.path.splitext(file_name)[-1] == extension:
file_name_path = os.path.join(root, file_name)
print file_name
print file_name_path # This is the full path of the filter file
Muitos usuários responderam com os.walk
respostas, que incluem todos os arquivos, mas também todos os diretórios e subdiretórios e seus arquivos.
import os
def files_in_dir(path, extension=''):
"""
Generator: yields all of the files in <path> ending with
<extension>
\param path Absolute or relative path to inspect,
\param extension [optional] Only yield files matching this,
\yield [filenames]
"""
for _, dirs, files in os.walk(path):
dirs[:] = [] # do not recurse directories.
yield from [f for f in files if f.endswith(extension)]
# Example: print all the .py files in './python'
for filename in files_in_dir('./python', '*.py'):
print("-", filename)
Ou para um caso em que você não precisa de um gerador:
path, ext = "./python", ext = ".py"
for _, _, dirfiles in os.walk(path):
matches = (f for f in dirfiles if f.endswith(ext))
break
for filename in matches:
print("-", filename)
Se você vai usar correspondências para outra coisa, convém fazer uma lista em vez de uma expressão geradora:
matches = [f for f in dirfiles if f.endswith(ext)]
Um método simples usando for
loop:
import os
dir = ["e","x","e"]
p = os.listdir('E:') #path
for n in range(len(p)):
name = p[n]
myfile = [name[-3],name[-2],name[-1]] #for .txt
if myfile == dir :
print(name)
else:
print("nops")
Embora isso possa ser mais generalizado.