获取目录中文件的过滤列表
我正在尝试使用Python获取目录中的文件列表,但我不想要所有文件的列表。
我基本上想要的是能够做以下的事情,但是使用Python而不是执行ls。
ls 145592*.jpg
如果没有内置的方法,我现在想写一个for循环遍历os.listdir()
的结果,并将所有匹配的文件追加到一个新的列表。
但是,该目录中有很多文件,因此我希望有一个更有效的方法(或内置方法)。
glob.glob('145592*.jpg')
glob.glob()
绝对是这样做的(按照Ignacio)。 但是,如果你确实需要更复杂的匹配,你可以用列表理解和re.match()
,就像这样:
files = [f for f in os.listdir('.') if re.match(r'[0-9]+.*\.jpg', f)]
更灵活,但正如你注意到的那样,效率较低。
把事情简单化:
import os relevant_path = "[path to folder]" included_extenstions = ['jpg', 'bmp', 'png', 'gif'] file_names = [fn for fn in os.listdir(relevant_path) if any(fn.endswith(ext) for ext in included_extensions)]
我更喜欢这种列表parsing的forms,因为它的英文读法很好。
我读了第四行:对于我的pathos.listdir中的每个fn,给我只有那些匹配我的任何一个扩展。
新手python程序员可能很难真正习惯于使用列表推导来进行过滤,并且它可能对于非常大的数据集有一些内存开销,但是为了列出一个目录和其他简单的string过滤任务,list列表理解会导致更加清洁可描述的代码。
这个devise唯一的事情就是它不会保护你不会传递一个string而不是一个列表的错误。 例如,如果您不小心将string转换为列表并最终检查string的所有字符,最终可能会产生大量的误报。
但是,比起一个难以理解的解决scheme,有一个容易解决的问题更好。
另外一个select:
>>> import os, fnmatch >>> fnmatch.filter(os.listdir('.'), '*.py') ['manage.py']
使用os.walkrecursion列出你的文件
import os root = "/home" pattern = "145992" alist_filter = ['jpg','bmp','png','gif'] path=os.path.join(root,"mydir_to_scan") for r,d,f in os.walk(path): for file in f: if file[-3:] in alist_filter and pattern in file: print os.path.join(root,file)
初步的代码
import glob import fnmatch import pathlib import os pattern = '*.py' path = '.'
解决scheme1 – 使用“glob”
# lookup in current dir glob.glob(pattern) In [2]: glob.glob(pattern) Out[2]: ['wsgi.py', 'manage.py', 'tasks.py']
解决scheme2 – 使用“os”+“fnmatch”
变种2.1 – 在当前目录中查找
# lookup in current dir fnmatch.filter(os.listdir(path), pattern) In [3]: fnmatch.filter(os.listdir(path), pattern) Out[3]: ['wsgi.py', 'manage.py', 'tasks.py']
变种2.2 – 查找recursion#查找recursion为dirpath,dirnames,在os.walk文件名(path):
if not filenames: continue pythonic_files = fnmatch.filter(filenames, pattern) if pythonic_files: for file in pythonic_files: print('{}/{}'.format(dirpath, file))
结果
./wsgi.py ./manage.py ./tasks.py ./temp/temp.py ./apps/diaries/urls.py ./apps/diaries/signals.py ./apps/diaries/actions.py ./apps/diaries/querysets.py ./apps/library/tests/test_forms.py ./apps/library/migrations/0001_initial.py ./apps/polls/views.py ./apps/polls/formsets.py ./apps/polls/reports.py ./apps/polls/admin.py
解决scheme3 – 使用“pathlib”
# lookup in current dir path_ = pathlib.Path('.') tuple(path_.glob(pattern)) # lookup recursive tuple(path_.rglob(pattern))
笔记:
- 在Python 3.4上testing
- 模块“pathlib”仅在Python 3.4中添加
- Python 3.5为glob.glob添加了一个recursion查找functionhttps://docs.python.org/3.5/library/glob.html#glob.glob 。 由于我在我的机器上安装了Python 3.4,所以我无法testing它。
import os dir="/path/to/dir" [x[0]+"/"+f for x in os.walk(dir) for f in x[2] if f.endswith(".jpg")]
这会给你一个完整path的jpg文件列表。 你可以用f
代替x[0]+"/"+f
来表示文件名。 你也可以用你想要的任何string条件replacef.endswith(".jpg")
。
你可能也喜欢更高级的方法(我已经实现并打包为findtools ):
from findtools.find_files import (find_files, Match) # Recursively find all *.txt files in **/home/** txt_files_pattern = Match(filetype='f', name='*.txt') found_files = find_files(path='/home', match=txt_files_pattern) for found_file in found_files: print found_file
可以安装
pip install findtools
你可以使用subprocess.check_ouput()作为
import subprocess list_files = subprocess.check_output("ls 145992*.jpg", shell=True)
当然,引号之间的string可以是任何你想在shell中执行的内容,并存储输出。