Tìm kiếm tệp trong thư mục hiện tại python

Ngoài việc là một ngôn ngữ lập trình có mục đích chung tuyệt vời, Python còn nổi tiếng là một ngôn ngữ tiện dụng để viết kịch bản. Do đó, đương nhiên, Python có hỗ trợ cho các loại hoạt động tìm kiếm tệp và đường dẫn mà người ta có thể thực hiện trong tập lệnh bash, chẳng hạn

quảng cáo

Tuy nhiên, việc tìm tệp trong Python có thể gây khó khăn nếu bạn không biết bắt đầu từ đâu, đặc biệt là khi bạn có thể chọn giữa nhiều thư viện để tìm và thao tác với đường dẫn và tệp. Trước phiên bản 3. 4, người ta sẽ sử dụng mô-đun

# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)
3 để tìm tệp và sử dụng mô-đun
# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)
4 để thực hiện các thao tác đường dẫn khác, chẳng hạn như lấy một thư mục có tên tệp tuyệt đối hoặc tạo một đường dẫn tuyệt đối từ một đường dẫn tương đối. Trăn 3. 4 đã giới thiệu mô-đun
# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)
5 dưới dạng API hướng đối tượng cho các đường dẫn hệ thống tệp

Hướng dẫn này sẽ tập trung vào mô-đun pathlib và hướng dẫn bạn những kiến ​​thức cơ bản về cách tìm tệp và thao tác với đường dẫn, bao gồm sử dụng mẫu toàn cục và tìm kiếm đệ quy. Chúng tôi cũng sẽ tìm hiểu cách tìm các đường dẫn khác nhau mà chúng tôi có thể cần sử dụng làm điểm bắt đầu. Ví dụ: làm thế nào bạn tìm thấy một tệp trong thư mục con của thư mục chính của người dùng, đường dẫn của tệp hiện đang thực thi là gì hoặc được đặt tên mô-đun Python, tên đó đến từ đâu?

Mô-đun PathLib. Xác định cấu trúc đường dẫn

Cho dù chúng tôi đang xử lý thư mục chính của người dùng, thư mục làm việc hiện tại hay thư mục chứa tệp Python đang thực thi, chúng tôi sẽ luôn cần một cách để xây dựng và thao tác các đường dẫn một cách mạnh mẽ. Mô-đun pathlib của Pyth n cung cấp hầu hết những gì chúng ta cần cho tác vụ này. Mặc dù mô-đun này có khái niệm về các đường dẫn “thuần túy” (tôi. e. , các đường dẫn mà bạn có thể thao tác mà không thực sự đề cập đến hệ thống tệp), điều phổ biến hơn nhiều là chúng ta chỉ muốn xây dựng một lớp đường dẫn cụ thể

quảng cáo

Ví dụ: chuyển tên tệp hoặc thư mục tới hàm tạo của lớp Đường dẫn sẽ tạo một đối tượng cụ thể thuộc loại PosixPath trên các hệ thống kiểu Linux hoặc Unix (như macOS) hoặc đối tượng WindowsPath trên Windows. Sử dụng lớp Path, gốc của các lớp cụ thể trong Python, cho phép mã mà chúng tôi sẽ trình bày trong bài viết này hoạt động trong cả hai môi trường

Tìm tệp trong thư mục hiện tại

Để bắt đầu sử dụng mô-đun Pathlib, chúng ta có thể chạy đoạn mã sau dưới dạng tệp hoặc từ dấu nhắc lệnh. Điều này sẽ liệt kê nội dung của thư mục làm việc hiện tại, nghĩa là, bất cứ nơi nào chúng tôi chạy nó từ đó (không phải nơi đặt tập lệnh Python)

# list_dirs.py
from pathlib import Path
here = Path(".")
files = here.glob("*")
for item in files:
    print(item)

Chúng tôi vượt qua trong một “. ” làm điểm khởi đầu để xây dựng Con đường. Sau đó, chúng ta có thể gọi phương thức toàn cục trên đối tượng đường dẫn để liệt kê tất cả các tệp trong thư mục này bằng cách sử dụng “*. ” Biểu thức chung, *, sẽ mở rộng thành “tất cả các tệp và thư mục”, giống như khi chúng ta sử dụng “ls *” trên Linux hoặc “dir *” trên Windows

quảng cáo

Liệt kê nội dung của thư mục tôi đang làm việc, tôi nhận được kết quả sau

Tôi đã cố gắng giữ cho thư mục này ở mức tối thiểu. Bạn có thể thấy chúng tôi liệt kê hai tệp python và thư mục con. Bằng cách thay đổi_______0_______6 thành

# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)
7, chúng tôi có thể chỉ tập trung vào các tệp Python hoặc chỉ định tên tệp đầy đủ, v.v.

Tìm kiếm tệp đệ quy trong Python

Phương pháp toàn cục cũng hỗ trợ cú pháp toàn cầu mở rộng,

# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)
8, cho phép bạn tìm kiếm tệp theo cách đệ quy. (Cú pháp này có thể mới đối với một số độc giả của tôi, nhưng đó là cú pháp tương tự được hỗ trợ bởi zsh và. gitignore nếu bạn đã quen thuộc với chúng). Mẫu toàn cầu này có nghĩa là “tìm kiếm ở đây và trong tất cả các thư mục con. ”

Quảng cáo
# list_dirs_recursive.py
from pathlib import Path
here = Path(".")
files = here.glob("**/*")
for item in files:
    print(item)

Lần này, chúng tôi thấy một tệp thử nghiệm mà tôi đã đặt trong thư mục cho mục đích này và tệp Python mới của chúng tôi

Tìm một tệp duy nhất theo cách đệ quy

Chỉ cần sử dụng một chút sáng tạo, chúng ta cũng có thể tìm kiếm đệ quy một tệp hoặc một tập hợp con các tệp. Ví dụ, nếu chúng ta chỉ muốn tìm một cái gì đó. txt bất kể nó bắt đầu từ thư mục làm việc hiện tại của chúng ta ở đâu, chúng ta có thể sử dụng “**/something. txt” làm mẫu chung

Quảng cáo
# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)

Đầu ra sẽ hiển thị cấu trúc thư mục liên quan đến nơi đặt đối tượng Đường dẫn

my_subdirectory/something.txt

Chúng tôi sử dụng vòng lặp for để lặp lại vì

# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)
3 trả về một trình tạo các đối tượng đường dẫn cùng loại với đường dẫn mà nó được gọi (trong trường hợp của chúng tôi là PosixPath)

Tìm một con đường tuyệt đối

Cho đến nay, chúng tôi đã chỉ ra các ví dụ về việc sử dụng các đường dẫn tương đối. Chúng tôi bắt đầu bằng cách đặt một biến thành

my_subdirectory/something.txt
0 và liên quan đến điều đó, chúng tôi có thể sử dụng “glob” để tìm “my_subdirectory một thứ gì đó. txt”, ví dụ. Nhưng đôi khi những gì chúng ta cần tìm là một đường dẫn tuyệt đối với thông tin đó. Sử dụng các đối tượng đường dẫn như đường dẫn Posix hoặc WindowsPath, chúng ta có thể sử dụng phương thức
my_subdirectory/something.txt
1 để lấy thông tin này. Giải quyết trả về một đường dẫn tuyệt đối. Nó cũng giải quyết mọi liên kết tượng trưng

Quảng cáo
"""Display some known relative and absolute paths"""
from pathlib import Path
here = Path(".")
file_path = Path("my_subdirectory/something.txt"
print(f"The absolute path to {here} is {here.resolve()}")
print(f"The absolute path to {file_path} is {file_path.resolve()}")

đầu ra

The absolute path to . is /Users/johnlockwood/paths-demo
The absolute path to my_subdirectory/something.txt is /Users/johnlockwood/paths-demo/my_subdirectory/something.txt

Lấy thư mục của tệp hiện đang thực thi

Bạn có thể đã biết rằng khi Python tải một mô-đun, chẳng hạn như tệp chương trình, nó sẽ đặt một biến cho mô-đun đó, “

my_subdirectory/something.txt
2“, thành tên tệp (tuyệt đối) của mô-đun. Do đó, với một tệp, chúng tôi có thể hiển thị vị trí của nó

# print_path.py
print(__file__)

đầu ra

/Users/johnlockwood/paths-demo/print_path.py

Biến

my_subdirectory/something.txt
2 không phải là một đối tượng đường dẫn, mà là một chuỗi. Tuy nhiên, bằng cách xây dựng một đường dẫn từ nó, chúng ta có thể truy vấn hai thuộc tính đặc biệt của một tệp, tên và cha, chúng sẽ chỉ cung cấp cho chúng ta phần tên của tệp và phần thư mục tương ứng

Quảng cáo
# print_directory.py
from pathlib import Path
file_path = Path(__file__)
print(f"The file {file_path.name} is located in directory {file_path.parent}.")

đầu ra

The file print_directory.py is located in directory /Users/johnlockwood/paths-demo.

Tạo tệp trong cùng thư mục với tệp Python

Nói chung, truy xuất thư mục của tệp bằng cách sử dụng thuộc tính

my_subdirectory/something.txt
4 sẽ hữu ích hơn là lấy tên của nó, vì giờ đây chúng ta có thể tạo một tên tệp tuyệt đối mà chúng ta có thể sử dụng để chuyển sang hàm khác. Đây là cách tiếp cận chính xác để định vị một tệp bên cạnh một tệp Python khác, vì — không giống như
my_subdirectory/something.txt
0 — đường dẫn do
my_subdirectory/something.txt
6 cung cấp sẽ luôn liên quan đến chính tệp đó, chứ không phải tệp được chạy từ đâu

Đối với các lớp Đường dẫn trong mô-đun pathlib, chúng ta có thể nối các thành phần đường dẫn lại với nhau bằng cách sử dụng toán tử “/” đã quá tải. (Lưu ý rằng chúng tôi sử dụng “/” cho điều này ngay cả trên Windows - nơi lớp Đường dẫn sẽ thực hiện đúng và sử dụng toán tử dấu gạch chéo ngược trong đường dẫn được tạo)

Với Đường dẫn được nhập và cung cấp những gì chúng tôi có cho đến nay, chúng tôi có thể tạo một tên tệp mới bằng cách sử dụng một lớp lót

# list_dirs_recursive.py
from pathlib import Path
here = Path(".")
files = here.glob("**/*")
for item in files:
    print(item)
0

Để xem lại, đoạn mã này tạo một Đường dẫn từ chuỗi __file__, sử dụng thuộc tính cha để lấy thư mục của tệp, sau đó sử dụng toán tử dấu gạch chéo để tạo một đối tượng Đường dẫn mới cho một tệp đầu ra trong cùng thư mục với tệp Python đang chạy

Có, nhưng tệp có tồn tại không?

Trong ví dụ trước, bạn có thể nhận thấy rằng chúng tôi đã tạo một đường dẫn không tồn tại. Đừng lo lắng, chúng ta có thể hỏi một đường dẫn để cho chúng ta biết liệu những gì nó trỏ đến có tồn tại hay không, chúng ta sử dụng (không có gì ngạc nhiên ở đây), phương thức

my_subdirectory/something.txt
7

quảng cáo

Đây là một ảnh chụp màn hình IPython nhanh minh họa cách thức hoạt động của nó

Tiếp theo, chúng ta hãy chú ý đến hai phương pháp "truy vấn" khác như vậy

Làm việc với Tệp và Thư mục

Khi chúng tôi tạo tên tệp mới dựa trên tên của biến tích hợp Python

my_subdirectory/something.txt
2, chúng tôi biết rằng
my_subdirectory/something.txt
2 là tên tệp, vì vậy sẽ rất hợp lý khi sử dụng thuộc tính
my_subdirectory/something.txt
4 để lấy thư mục chứa tệp. Tất nhiên, được cung cấp một đường dẫn tuyệt đối đến một thư mục,
my_subdirectory/something.txt
4 hành xử “khác”, trả về thư mục chứa thư mục này. Ví dụ

# list_dirs_recursive.py
from pathlib import Path
here = Path(".")
files = here.glob("**/*")
for item in files:
    print(item)
1

đầu ra mẫu

# list_dirs_recursive.py
from pathlib import Path
here = Path(".")
files = here.glob("**/*")
for item in files:
    print(item)
2

Cho đến nay, trong các ví dụ đơn giản này, chúng ta luôn biết loại Đường dẫn mà chúng ta đang xử lý, nhưng nếu chúng ta không biết, các lớp đường dẫn cụ thể mà chúng ta đang xử lý có thể cho chúng ta biết nếu chúng ta đang đề cập đến . Chúng tôi sẽ sử dụng các phương thức này trong ví dụ sau

Thí dụ. Liệt kê đệ quy các tệp và thư mục trong Python

Hãy tập hợp một vài kỹ thuật mà chúng ta đã thảo luận để xây dựng một mẫu trong đó chúng ta thực hiện tìm kiếm đệ quy cho tất cả các tệp và thư mục và in kết quả

Quảng cáo
# list_dirs_recursive.py
from pathlib import Path
here = Path(".")
files = here.glob("**/*")
for item in files:
    print(item)
3

đầu ra viết tắt

# list_dirs_recursive.py
from pathlib import Path
here = Path(".")
files = here.glob("**/*")
for item in files:
    print(item)
4

Tìm các tập tin và thư mục khác

Lấy thư mục chính của người dùng bằng Python

Để lấy thư mục chính của người dùng, chỉ cần gọi phương thức lớp “

"""Display some known relative and absolute paths"""
from pathlib import Path
here = Path(".")
file_path = Path("my_subdirectory/something.txt"
print(f"The absolute path to {here} is {here.resolve()}")
print(f"The absolute path to {file_path} is {file_path.resolve()}")
4” trên lớp Đường dẫn. Điều này sẽ truy xuất thư mục chính của người dùng cho dù trong môi trường giống như Linux hay trên Windows

# list_dirs_recursive.py
from pathlib import Path
here = Path(".")
files = here.glob("**/*")
for item in files:
    print(item)
5

Đầu ra của khóa học sẽ phụ thuộc vào người dùng

Lấy thư mục làm việc hiện tại

Để giúp chúng tôi bắt đầu xây dựng các đối tượng Đường dẫn, tôi đã sử dụng đường dẫn được cung cấp bởi

my_subdirectory/something.txt
0 để truy xuất thư mục làm việc hiện tại. Tôi đã kiểm tra rằng phương pháp đó hoạt động ngay cả khi bạn thay đổi thư mục làm việc hiện tại theo chương trình, nhưng có một cách khác để thực hiện điều này có lẽ rõ ràng hơn một chút.
"""Display some known relative and absolute paths"""
from pathlib import Path
here = Path(".")
file_path = Path("my_subdirectory/something.txt"
print(f"The absolute path to {here} is {here.resolve()}")
print(f"The absolute path to {file_path} is {file_path.resolve()}")
6. Như bạn có thể mong đợi, giống như
"""Display some known relative and absolute paths"""
from pathlib import Path
here = Path(".")
file_path = Path("my_subdirectory/something.txt"
print(f"The absolute path to {here} is {here.resolve()}")
print(f"The absolute path to {file_path} is {file_path.resolve()}")
7,
"""Display some known relative and absolute paths"""
from pathlib import Path
here = Path(".")
file_path = Path("my_subdirectory/something.txt"
print(f"The absolute path to {here} is {here.resolve()}")
print(f"The absolute path to {file_path} is {file_path.resolve()}")
8 là một phương thức của lớp, vì vậy bạn có thể gọi nó trên chính lớp đó — bạn không cần một thể hiện

Giống như hàm tạo chuỗi Đường dẫn, cả

"""Display some known relative and absolute paths"""
from pathlib import Path
here = Path(".")
file_path = Path("my_subdirectory/something.txt"
print(f"The absolute path to {here} is {here.resolve()}")
print(f"The absolute path to {file_path} is {file_path.resolve()}")
6 và
The absolute path to . is /Users/johnlockwood/paths-demo
The absolute path to my_subdirectory/something.txt is /Users/johnlockwood/paths-demo/my_subdirectory/something.txt
0 đều trả về các đối tượng Đường dẫn cụ thể, vì vậy chúng ta có thể tạo đường dẫn ngay lập tức bằng cách sử dụng toán tử dấu gạch chéo. Chẳng hạn, bạn có cần truy vấn xem người dùng đã cài đặt cấu hình cho giao diện dòng lệnh AWS của Amazon chưa?

Quảng cáo
# list_dirs_recursive.py
from pathlib import Path
here = Path(".")
files = here.glob("**/*")
for item in files:
    print(item)
6

Thí dụ. Tạo một thư mục trong thư mục chính của người dùng trong Python

Lớp cụ thể

The absolute path to . is /Users/johnlockwood/paths-demo
The absolute path to my_subdirectory/something.txt is /Users/johnlockwood/paths-demo/my_subdirectory/something.txt
1 có nhiều hữu ích ngoài những thứ chúng tôi đang tập trung vào ở đây, tôi. e. , những thứ liên quan đến việc tìm tệp và thư mục

Tuy nhiên, vì đây là một trường hợp sử dụng phổ biến nên chúng tôi nghĩ rằng mình sẽ đưa ra một ví dụ sử dụng phương pháp

The absolute path to . is /Users/johnlockwood/paths-demo
The absolute path to my_subdirectory/something.txt is /Users/johnlockwood/paths-demo/my_subdirectory/something.txt
2. Bắt đầu với thư mục chính của người dùng, chúng ta sẽ tạo một thư mục “ẩn” cho dòng lệnh CodeSolid giả định

Bởi vì việc tạo một thư mục sẽ không thành công với một ngoại lệ nếu đường dẫn đã tồn tại, chúng tôi kiểm tra điều này và thực hiện đúng

# list_dirs_recursive.py
from pathlib import Path
here = Path(".")
files = here.glob("**/*")
for item in files:
    print(item)
7

Tìm đường dẫn và tệp mô-đun Python

Không giống như thư mục làm việc hiện tại và thư mục chính của người dùng, là những vị trí phổ biến mà chúng ta có thể muốn đọc hoặc ghi tệp và thư mục, có lẽ ít phổ biến hơn khi cần tìm các vị trí liên quan đến nơi Python sẽ tìm kiếm mô-đun hoặc vị trí thực tế chứa . Tuy nhiên, đôi khi điều này có thể giúp khắc phục sự cố, đặc biệt nếu mã sai dường như đang được tải hoặc mọi thứ không hoạt động như bạn mong đợi

Khám phá PYTHONPATH và sys. đường dẫn Biến

Như bạn đã biết, biến môi trường PYTHONPATH thêm đường dẫn tìm kiếm vào các vị trí mặc định mà Python sẽ tìm kiếm khi bạn nhập mô-đun. Do đó, bạn có thể đọc nó như bất kỳ biến môi trường nào

Quảng cáo
# list_dirs_recursive.py
from pathlib import Path
here = Path(".")
files = here.glob("**/*")
for item in files:
    print(item)
8

Tuy nhiên, nếu bạn đang khắc phục sự cố, thì việc đọc biến môi trường có thể là không đủ, vì điều bạn thực sự quan tâm là sự kết hợp hiệu quả của PYTHONPATH cộng với bất kỳ đường dẫn tìm kiếm mặc định nào. Với mục đích này, thuộc tính

The absolute path to . is /Users/johnlockwood/paths-demo
The absolute path to my_subdirectory/something.txt is /Users/johnlockwood/paths-demo/my_subdirectory/something.txt
3 là một công cụ tiện dụng hơn nhiều

# list_dirs_recursive.py
from pathlib import Path
here = Path(".")
files = here.glob("**/*")
for item in files:
    print(item)
9

Phần tử đầu tiên của mảng sẽ là thư mục đã tải mô-đun hiện tại hoặc một chuỗi rỗng, như được hiển thị ở đây, nếu Python được khởi chạy theo cách tương tác. Sau đó, bạn sẽ thấy các mục PYTHONPATH và vị trí tìm kiếm mô-đun mặc định

PYTHONPATH cho chúng ta thấy đường dẫn mô-đun có thể đã bị thay đổi như thế nào, trong khi

The absolute path to . is /Users/johnlockwood/paths-demo
The absolute path to my_subdirectory/something.txt is /Users/johnlockwood/paths-demo/my_subdirectory/something.txt
3 cung cấp cho chúng ta tất cả các đường dẫn mà mô-đun có thể đã được tải từ đó. Tuy nhiên, chúng ta thậm chí có thể đi xa hơn thế này và kiểm tra vị trí chính xác mà Python đã tải (hoặc thậm chí sẽ tải) một mô-đun cụ thể từ đó. Cách đơn giản nhất để thực hiện việc này đối với một mô-đun đã tải là sử dụng bạn của chúng ta, thuộc tính
my_subdirectory/something.txt
2. hoặc ví dụ

Tìm tên tệp từ đó mô-đun Python đã được tải

# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)
0

Sử dụng một phương pháp hơi kém tin cậy hơn, đôi khi chúng ta có thể tìm thấy đường dẫn mà từ đó một mô-đun sẽ được tải ngay cả khi không thực sự tải nó. Điều này thường hoạt động đối với các mô-đun do người dùng xác định và các mô-đun thư viện thời gian chạy Python không được tải bởi trình tải mô-đun “FrozenLoader”. Như chúng ta sẽ thấy bên dưới, nó không hoạt động tốt đối với mô-đun “os”

Quảng cáo
# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)
1

đầu ra mẫu

# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)
2

Bớt tư tưởng

Như chúng ta đã thấy, thư viện pathlib của Python chứa hầu hết những gì bạn cần để tìm tệp trong Python và cũng liệt kê các thư mục và tệp theo cách đệ quy. Tuy nhiên, như chúng tôi đã đề xuất ngay từ đầu, có sự trùng lặp đáng kể giữa những gì có sẵn trong

# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)
5 và những gì chúng tôi tìm thấy trong các thư viện
The absolute path to . is /Users/johnlockwood/paths-demo
The absolute path to my_subdirectory/something.txt is /Users/johnlockwood/paths-demo/my_subdirectory/something.txt
7 và
# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)
4. Chúng tôi đã chọn tập trung vào
# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)
5 ở đây vì chúng tôi tin rằng trong nhiều trường hợp, điều đó làm cho mã thuận tiện hơn khi làm việc và chúng tôi không thấy nhiều điểm trong hướng dẫn dạy bạn hai cách để làm điều gì đó nếu một là đủ. Điều đó có nghĩa là, nếu bạn có mã dựa trên
# find_file.py
from pathlib import Path
here = Path(".")
files = here.glob("**/something.txt")
for item in files:
    print(item)
4 hoạt động tốt, thì thành thật mà nói, chúng tôi thấy không có lý do thuyết phục nào để làm lại mã đó

Cuối cùng, đối với những trường hợp như thế này, đôi khi chúng ta chỉ cần mở bảng điều khiển, gõ

# print_path.py
print(__file__)
1 và đắm mình trong sự khôn ngoan của Zen of Python