geekdoc-python-zh/docs/askpython/list-files-in-a-directory-u...

13 KiB
Raw Permalink Blame History

如何用 Python 列出一个目录下的文件?

原文:https://www.askpython.com/python/examples/list-files-in-a-directory-using-python

在本教程中,我们将介绍如何使用 Python 列出目录中的文件。

Python 是一种通用语言,用于各种领域,如数据科学、机器学习,甚至是 Web 开发。Python 语言的应用似乎没有限制。

因此,似乎很简单的 Python 可以用来列出任何系统中的文件和目录。这篇文章的目的是向读者阐明使用 Python 在系统中列出文件的方法。

使用 Python 列出目录中的所有文件

为了使用 Python 与系统中的目录进行交互,使用了os库。

1.使用“操作系统”库

我们要练习的方法是 listdir()。顾名思义,它用于列出目录中的项目。

# Importing the os library
import os

# The path for listing items
path = '.'

# The list of items
files = os.listdir(path)

# Loop to print each filename separately
for filename in files:
	print(filename)

输出:

game_file.py
hi-lo_pygame.py
Journaldev
list_files1.py
hi_lo_pygame.mp4
test.py
list_files.py
my_program.cpp
a.out
cut.cpp

Linux 用户可以在终端上使用标准的ls命令轻松匹配上面的输出。

List Files Python Ls

List Items using ls command

正如我们所看到的,每个方法的输出都是匹配的。


2.使用“glob”库

glob主要是一个文件名模式匹配库,但是它可以通过以下方式列出当前目录中的项目:

# Importing the glob library
import glob 

# Path to the directory
path = ''

# or 
# path = './'

# Extract the list of filenames
files = glob.glob(path + '*', recursive=False)

# Loop to print the filenames
for filename in files:
	print(filename)

输出:

game_file.py
hi-lo_pygame.py
Journaldev
list_files1.py
hi_lo_pygame.mp4
test.py
list_files.py
my_program.cpp
a.out
cut.cpp

通配符'*'用于匹配当前目录中的所有项目。因为我们希望显示当前目录的条目,所以我们需要关闭glob()函数的递归特性。


3.仅列出当前目录中的文件

在上面的方法中python 代码返回当前目录中的所有项目,而不管它们的性质如何。我们可以使用os库中的path.isfile()函数只提取文件。

# Importing the os library
import os

# The path for listing items
path = '.'

# List of only files
files = [f for f in os.listdir(path) if os.path.isfile(f)]

# Loop to print each filename separately
for filename in files:
	print(filename)

输出:

game_file.py
hi-lo_pygame.py
list_files1.py
hi_lo_pygame.mp4
test.py
list_files.py
my_program.cpp
a.out
cut.cpp

在上面的代码片段中, List Comprehension 用于过滤掉那些实际上是文件的项目。

这里需要注意的另一个关键点是,上面的代码不适用于其他目录,因为变量'f'不是绝对路径,而是当前目录的相对路径。


递归列出目录中的所有文件

为了打印目录及其子目录中的文件,我们需要递归地遍历它们。

1.使用“操作系统”库

walk()方法的帮助下,我们可以逐个遍历目录中的每个子目录。

# Importing the os library
import os

# The path for listing items
path = './Documents/'

# List of files in complete directory
file_list = []

"""
	Loop to extract files inside a directory

	path --> Name of each directory
	folders --> List of subdirectories inside current 'path'
	files --> List of files inside current 'path'

"""
for path, folders, files in os.walk(path):
	for file in files:
		file_list.append(os.path.join(path, file))

# Loop to print each filename separately
for filename in file_list:
	print(filename)

输出:

./Documents/game_file.py
./Documents/hi-lo_pygame.py
./Documents/list_files1.py
./Documents/hi_lo_pygame.mp4
./Documents/test.py
./Documents/list_files.py
./Documents/my_program.cpp
./Documents/a.out
./Documents/cut.cpp
./Documents/Journaldev/mastermind.py
./Documents/Journaldev/blackjack_terminal.py
./Documents/Journaldev/lcm.cpp
./Documents/Journaldev/super.cpp
./Documents/Journaldev/blackjack_pygame.py
./Documents/Journaldev/test.java

os.walk()方法简单地跟随每个子目录,默认情况下以自顶向下的方式提取文件。有三个迭代器用于遍历os.walk()函数的输出:

  • **path**–该变量包含函数在某次迭代中观察的当前目录
  • **folders**–该变量是'path'目录中的目录列表。
  • **files**–目录'path'中的文件列表。

join()方法用于将文件名与其父目录连接起来,为我们提供文件的相对路径。


2.使用“glob”库

类似于上面的过程,glob可以递归地访问每个目录,提取所有项目并返回。

# Importing the glob library
import glob 

# Importing the os library
import os

# Path to the directory
path = './Documents/'

# Extract all the list of items recursively
files = glob.glob(path + '**/*', recursive=True)

# Filter only files
files = [f for f in files if os.path.isfile(f)]

# Loop to print the filenames
for filename in files:
	print(filename)

输出:

./Documents/game_file.py
./Documents/hi-lo_pygame.py
./Documents/list_files1.py
./Documents/hi_lo_pygame.mp4
./Documents/test.py
./Documents/list_files.py
./Documents/my_program.cpp
./Documents/a.out
./Documents/cut.cpp
./Documents/Journaldev/mastermind.py
./Documents/Journaldev/blackjack_terminal.py
./Documents/Journaldev/lcm.cpp
./Documents/Journaldev/super.cpp
./Documents/Journaldev/blackjack_pygame.py
./Documents/Journaldev/test.java

与 path 变量一起使用的符号'**'告诉glob()函数匹配任何子目录中的文件。'*'告诉函数匹配一个目录中的所有项目。

因为我们希望只提取完整目录中的文件,所以我们使用之前使用的isfile()函数过滤掉这些文件。


列出一个目录中的所有子目录

我们可以列出特定目录中的所有子目录,而不是列出文件。

# Importing the os library
import os

# The path for listing items
path = './Documents/'

# List of folders in complete directory
folder_list = []

"""
	Loop to extract folders inside a directory

	path --> Name of each directory
	folders --> List of subdirectories inside current 'path'
	files --> List of files inside current 'path'

"""
for path, folders, files in os.walk(path):
	for folder in folders:
		folder_list.append(os.path.join(path, folder))

# Loop to print each foldername separately
for foldername in folder_list:
	print(foldername)

输出:

./Documents/Journaldev

列出文件和目录的微小区别在于os.walk()函数过程中迭代器的选择。对于文件,我们迭代 files 变量。这里,我们循环遍历 folders 变量。


用绝对路径列出目录中的文件

一旦我们知道如何列出目录中的文件,那么显示绝对路径就是小菜一碟。abspath()方法为我们提供了文件的绝对路径。

# Importing the os library
import os

# The path for listing items
path = './Documents/'

# List of files in complete directory
file_list = []

"""
	Loop to extract files inside a directory

	path --> Name of each directory
	folders --> List of subdirectories inside current 'path'
	files --> List of files inside current 'path'

"""
for path, folders, files in os.walk(path):
	for file in files:
		file_list.append(os.path.abspath(os.path.join(path, file)))

# Loop to print each filename separately
for filename in file_list:
	print(filename)

输出:

/home/aprataksh/Documents/game_file.py
/home/aprataksh/Documents/hi-lo_pygame.py
/home/aprataksh/Documents/list_files1.py
/home/aprataksh/Documents/hi_lo_pygame.mp4
/home/aprataksh/Documents/test.py
/home/aprataksh/Documents/list_files.py
/home/aprataksh/Documents/my_program.cpp
/home/aprataksh/Documents/a.out
/home/aprataksh/Documents/cut.cpp
/home/aprataksh/Documents/Journaldev/mastermind.py
/home/aprataksh/Documents/Journaldev/blackjack_terminal.py
/home/aprataksh/Documents/Journaldev/lcm.cpp
/home/aprataksh/Documents/Journaldev/super.cpp
/home/aprataksh/Documents/Journaldev/blackjack_pygame.py
/home/aprataksh/Documents/Journaldev/test.java

这里需要注意的一点是,abspath()必须提供文件的相对路径,这也是join()函数的目的。


通过匹配模式列出目录中的文件

有多种方法可以过滤出符合特定模式的文件名。让我们一个一个地看一遍。

1.使用“fnmatch”库

顾名思义,fnmatch是一个文件名模式匹配库。将fnmatch与我们的标准文件名提取库一起使用,我们可以过滤出那些匹配特定模式的文件。

# Importing the os and fnmatch library
import os, fnmatch

# The path for listing items
path = './Documents/'

# List of files in complete directory
file_list = []

"""
	Loop to extract files containing word "file" inside a directory

	path --> Name of each directory
	folders --> List of subdirectories inside current 'path'
	files --> List of files inside current 'path'

"""
print("List of files containing \"file\" in them")
for path, folders, files in os.walk(path):
	for file in files:
		if fnmatch.fnmatch(file, '*file*'):
			file_list.append(os.path.join(path, file))

# Loop to print each filename separately
for filename in file_list:
	print(filename)

输出:

List of files containing "file" in them
./Documents/game_file.py
./Documents/list_files1.py
./Documents/list_files.py

fnmatch()函数接受两个参数,文件名后面跟着要匹配的模式。在上面的代码中,我们查看了所有包含单词file的文件。


2.使用“glob”库

正如我们之前提到的,glob's的主要目的是文件名模式匹配。

# Importing the glob library
import glob 

# Importing the os library
import os

# Path to the directory
path = './Documents/'

# Extract items containing numbers in name
files = glob.glob(path + '**/*[0-9]*.*', recursive=True)

# Filter only files
files = [f for f in files if os.path.isfile(f)]

# Loop to print the filenames
for filename in files:
	print(filename)

输出:

./Documents/list_files1.py

上面的模式匹配正则表达式 '**/*[0-9]*.*'可以解释为:

  • **'**'**–遍历路径内的所有子目录
  • **'/*'**–文件名可以以任何字符开头
  • **'[0-9]'**–文件名中包含一个数字
  • **'*.*'**–文件名可以以任何字符结尾,可以有任何扩展名

3.使用“pathlib”库

遵循面向对象的方式与文件系统交互。库中的rglob()函数可用于通过某个路径对象递归提取文件列表。

这些文件列表可以使用rglob()函数中的模式进行过滤。

# Importing the pathlib library
import pathlib

# Creating a Path object
path = pathlib.Path('./Documents/')

# Extracting a list of files starting with 'm'
files = path.rglob('m*')

# Loop to print the files separately
for file in files:
	print(file)

输出:

Documents/my_program.cpp
Documents/Journaldev/mastermind.py

上面的代码片段用于列出所有以字母'm'开头的文件。


列出目录中具有特定扩展名的文件

在 Python 中列出带有特定扩展名的文件有点类似于模式匹配。为此,我们需要创建一个关于文件扩展名的模式。

# Importing the os and fnmatch library
import os, fnmatch

# The path for listing items
path = './Documents/'

# List to store filenames 
file_list = []

"""
	Loop to extract python files 

	path --> Name of each directory
	folders --> List of subdirectories inside current 'path'
	files --> List of files inside current 'path'

"""
print("List of python files in the directory:")
for path, folders, files in os.walk(path):
	for file in files:
		if fnmatch.fnmatch(file, '*.py'):
			file_list.append(os.path.join(path, file))

# Loop to print each filename separately
for filename in file_list:
	print(filename)

输出:

List of python files in the directory:
./Documents/game_file.py
./Documents/hi-lo_pygame.py
./Documents/list_files1.py
./Documents/test.py
./Documents/list_files.py
./Documents/Journaldev/mastermind.py
./Documents/Journaldev/blackjack_terminal.py
./Documents/Journaldev/blackjack_pygame.py

fnmatch()函数过滤掉那些以'.py'结尾的文件,也就是 python 文件。如果我们想要提取不同扩展名的文件,那么我们必须修改这部分代码。例如,为了只获取 C++文件,必须使用'.cpp'

这总结了使用 Python 获取目录中文件列表的方法。


结论

可以有多种方法来解决手头的任何问题最方便的方法并不总是答案。关于这篇文章Python 程序员必须知道我们可以在目录中列出文件的每一种方式。

我们希望这篇文章容易理解。如有任何疑问或建议,欢迎在下方留言。