我正在尝试计算文件夹及其所有子文件夹中的所有文件 例如,如果我的文件夹如下所示:
file1.txt
subfolder1/
├── file2.txt
├── subfolder2/
│ ├── file3.txt
│ ├── file4.txt
│ └── subfolder3/
│ └── file5.txt
└── file6.txt
file7.txt
我想要7号。
我尝试的第一件事是一个递归函数,它计算所有文件并为每个文件夹调用自身
def get_file_count(directory: str) -> int:
count = 0
for filename in os.listdir(directory):
file = (os.path.join(directory, filename))
if os.path.isfile(file):
count += 1
elif os.path.isdir(file):
count += get_file_count(file)
return count
这种方式可行,但对于大目录需要花费大量时间。
我还记得这篇文章,它展示了一种使用 win32com 计算文件夹总大小的快速方法,我想知道这个库是否也提供了一种方法来完成我正在寻找的事情。 但是经过搜索,我只找到了这个
fso = com.Dispatch("Scripting.FileSystemObject")
folder = fso.GetFolder(".")
size = folder.Files.Count
但这只会返回目标文件夹(而不是其子文件夹)中的文件数
那么,你知道python中有没有一个最优函数返回一个文件夹及其所有子文件夹中的文件数?
IIUC,你可以做到
sum(len(files) for _, _, files in os.walk('path/to/folder'))
或者,为了避免
len
可能稍微好一点的性能:
sum(1 for _, _, files in os.walk('folder_test') for f in files)
此代码将显示所有目录条目的计数,这些目录条目不是来自指定根目录的目录(例如,普通文件、符号链接)。
包括时间和测试中使用的实际路径名:
from glob import glob, escape
import os
import time
def get_file_count(directory: str) -> int:
count = 0
for filename in glob(os.path.join(escape(directory), '*')):
if os.path.isdir(filename):
count += get_file_count(filename)
else:
count += 1
return count
start = time.perf_counter()
count = get_file_count('/Volumes/G-DRIVE Thunderbolt 3')
end = time.perf_counter()
print(count)
print(f'{end-start:.2f}s')
输出:
166231
2.38s
我用过 os.walk()
我的例子,希望对你有帮助
def file_dir():
directories = []
res = {}
cwd = os.getcwd()
for root, dirs, files in os.walk(cwd):
for file in files:
if file.endswith(".tsv"):
directories.append(os.path.join(root, file))
res['dir'] = directories
return res
你也可以直接使用命令:
find DIR_NAME -type f | wc -l
这将返回所有文件的数量 使用
os.system()
这可以从 python 完成。
另一个使用库
os
和Path
的解决方案:
from pathlib import Path
from os.path import isfile
len([x for x in Path('./dir1').rglob('*') if isfile(x)])
正确的方法是像其他人指出的那样使用
os.walk
,但要给出另一个尽可能类似于你原来的解决方案:
os.scandir
来避免构建整个列表的成本,它应该快得多:
def get_file_count(directory: str) -> int:
count = 0
for entry in os.scandir(directory):
if entry.is_file():
count += 1
elif entry.is_dir():
count += get_file_count(os.path.join(directory, entry.name))
return count
这是另一种方式。
import os
import re
import pandas as pd
def count_files(top, pattern, list_files):
top = os.path.abspath(os.path.expanduser(top))
res = []
for root, dirs, files in os.walk(top):
name_space = os.path.relpath(root, top)
level = os.path.normpath(name_space).count(os.sep) + 1 if name_space != '.' else 0
matches = [file for file in files if re.search(pattern, file)]
if matches:
if list_files:
res.append((pattern, level, name_space, len(matches), matches))
else:
res.append((pattern, level, name_space, len(matches)))
if list_files:
df = pd.DataFrame(res, columns=['pattern', 'level', 'name_space', 'count', 'files'])
else:
df = pd.DataFrame(res, columns=['pattern', 'level', 'name_space', 'count'])
return df
考虑以下目录结构
rajulocal@hogwarts ~/x/x5 % tree -a
.
├── analysis.txt
├── count_files.ipynb
├── d1
│ ├── d2
│ │ ├── d3
│ │ │ └── f5.txt
│ │ ├── f3.txt
│ │ └── f4.txt
│ ├── f2.txt
│ └── f6.txt
├── f1.txt
├── f7.txt
└── .ipynb_checkpoints
└── count_files-checkpoint.ipynb
4 directories, 10 files
计算每个目录中的文本文件(即以.txt结尾的文件)
rajulocal@hogwarts ~/x/x5 % ipython
Python 3.10.6 (main, Oct 24 2022, 16:07:47) [GCC 11.2.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.6.0 -- An enhanced Interactive Python. Type '?' for help.
...
In [2]:
df = count_files("~/x/x5", "\.txt", False)
df
Out[2]:
pattern level name_space count
0 \.txt 0 . 3
1 \.txt 1 d1 2
2 \.txt 2 d1/d2 2
3 \.txt 3 d1/d2/d3 1
查看这些文件是什么
In [3]:
df = count_files("~/x/x5", "\.txt", True)
df
Out[3]:
pattern level name_space count files
0 \.txt 0 . 3 [analysis.txt, f1.txt, f7.txt]
1 \.txt 1 d1 2 [f6.txt, f2.txt]
2 \.txt 2 d1/d2 2 [f4.txt, f3.txt]
3 \.txt 3 d1/d2/d3 1 [f5.txt]
获取文件总数
In [4]:
df['count'].sum()
Out[4]:
8
统计以.ipynb结尾的文件(ipython notebook文件)
In [5]:
df = count_files("~/x/x5", "\.ipynb", True)
df
Out[5]:
pattern level name_space count files
0 \.ipynb 0 . 1 [count_files.ipynb]
1 \.ipynb 1 .ipynb_checkpoints 1 [count_files-checkpoint.ipynb]
In [6]:
df['count'].sum()
Out[6]:
2
统计所有文件
In [7]:
df = count_files("~/x/x5", ".*", False)
df
Out[7]:
pattern level name_space count
0 .* 0 . 4
1 .* 1 .ipynb_checkpoints 1
2 .* 1 d1 2
3 .* 2 d1/d2 2
4 .* 3 d1/d2/d3 1
In [8]:
df['count'].sum()
Out[8]:
10
与树命令中的文件计数相匹配。