Có một vài cách khác nhau để thực hiện điều gì đó như thế này, tôi sẽ đưa ra hai cách tiếp cận nhanh chóng để bạn lựa chọn: nhanh và bẩn, so với dài hơn và ít bẩn hơn (mặc dù, đó là đêm thứ sáu nên chúng tôi ' lại được phép đi một chút điên rồ).
1. Nhanh (và bẩn)
này liên quan đến chỉ viết một biểu thức chính quy (có thể được chia thành nhiều) sử dụng để lọc các bộ sưu tập các tập tin trong một lần mua sắm nhanh chóng.
(Chỉ có hai dòng nhận xét là thực sự quan trọng đối với khái niệm này.)
$directory = new RecursiveDirectoryIterator(__DIR__);
$flattened = new RecursiveIteratorIterator($directory);
// Make sure the path does not contain "/.Trash*" folders and ends eith a .php or .html file
$files = new RegexIterator($flattened, '#^(?:[A-Z]:)?(?:/(?!\.Trash)[^/]+)+/[^/]+\.(?:php|html)$#Di');
foreach($files as $file) {
echo $file . PHP_EOL;
}
Cách tiếp cận này có một số vấn đề, mặc dù nó là nhanh chóng thực hiện được chỉ là một one-liner (mặc dù regex có thể là một nỗi đau để giải mã).
2. Ít nhanh chóng (và ít bẩn)
Một cách tiếp cận tái sử dụng được nhiều hơn là tạo ra một vài bộ lọc bespoke (sử dụng regex, hoặc bất cứ điều gì bạn muốn!) Để gọt xuống danh sách các sẵn các mục trong số RecursiveDirectoryIterator
ban đầu chỉ dành cho những mục bạn muốn. Sau đây chỉ là một ví dụ, được viết nhanh cho bạn, mở rộng RecursiveRegexIterator
.
Chúng tôi bắt đầu với một lớp cơ sở mà công việc chính của họ là giữ một regex mà chúng tôi muốn lọc, mọi thứ khác được hoãn lại cho RecursiveRegexIterator
. Lưu ý rằng lớp là abstract
vì nó không thực sự là làm bất kỳ điều gì hữu ích: việc lọc thực tế sẽ được thực hiện bởi hai lớp sẽ mở rộng lớp này. Ngoài ra, nó có thể được gọi là FilesystemRegexFilter
nhưng không có gì buộc nó (ở cấp độ này) để lọc các lớp liên quan đến hệ thống tập tin (tôi đã chọn một tên tốt hơn, nếu tôi không khá buồn ngủ).
abstract class FilesystemRegexFilter extends RecursiveRegexIterator {
protected $regex;
public function __construct(RecursiveIterator $it, $regex) {
$this->regex = $regex;
parent::__construct($it, $regex);
}
}
Hai lớp này là bộ lọc rất cơ bản, hoạt động trên tên tệp và tên thư mục tương ứng.
class FilenameFilter extends FilesystemRegexFilter {
// Filter files against the regex
public function accept() {
return (! $this->isFile() || preg_match($this->regex, $this->getFilename()));
}
}
class DirnameFilter extends FilesystemRegexFilter {
// Filter directories against the regex
public function accept() {
return (! $this->isDir() || preg_match($this->regex, $this->getFilename()));
}
}
Để đưa những thành thực tế, lặp sau đệ quy về nội dung của thư mục trong đó kịch bản cư trú (bạn có thể chỉnh sửa này!) Và lọc ra các .Trash
thư mục (bằng cách đảm bảo rằng tên thư mục khớp với regex được tạo thủ công đặc biệt) và chỉ chấp nhận các tệp PHP và HTML.
$directory = new RecursiveDirectoryIterator(__DIR__);
// Filter out ".Trash*" folders
$filter = new DirnameFilter($directory, '/^(?!\.Trash)/');
// Filter PHP/HTML files
$filter = new FilenameFilter($filter, '/\.(?:php|html)$/');
foreach(new RecursiveIteratorIterator($filter) as $file) {
echo $file . PHP_EOL;
}
Lưu ý đặc biệt là do bộ lọc của chúng tôi đệ quy, nên chúng tôi có thể chọn cách sử dụng để lặp lại chúng. Ví dụ, chúng ta có thể dễ dàng hạn chế mình để chỉ quét lên đến 2 cấp độ sâu (bao gồm cả các thư mục khởi động) bằng cách thực hiện:
$files = new RecursiveIteratorIterator($filter);
$files->setMaxDepth(1); // Two levels, the parameter is zero-based.
foreach($files as $file) {
echo $file . PHP_EOL;
}
Đây cũng là siêu dễ dàng để thêm nhưng nhiều bộ lọc (bằng instantiating hơn về lọc của chúng tôi các lớp với các regex khác nhau, hoặc bằng cách tạo các lớp lọc mới) cho các nhu cầu lọc chuyên biệt hơn (ví dụ: kích thước tệp, độ dài đường dẫn đầy đủ, v.v.).
P.S. Hmm câu trả lời này một chút; Tôi đã cố gắng giữ cho nó ngắn gọn nhất có thể (thậm chí loại bỏ những vũng nước khổng lồ). Xin lỗi nếu kết quả ròng để lại câu trả lời không mạch lạc.
Thực sự đánh giá cao cách tiếp cận ít nhanh hơn (và ít bẩn) nó chứng minh chính xác những gì tôi đang tìm kiếm. Cảm ơn. Mặc dù lỗi nhanh chóng và bị lỗi đã xảy ra với Lỗi nghiêm trọng: Ngoại lệ chưa được thực hiện 'UnexpectedValueException' với thông báo 'RecursiveDirectoryIterator :: __ construct (/var/www/html/.Trash-0) – Chris
Lỗi là không có gì thực sự sai với mã (thanh không 'cố gắng'-ing đủ cứng), nguyên nhân có khả năng nhất là quyền của thư mục (hoặc thiếu nó). Vui vì bạn hài lòng với sự thay thế tốt hơn. :) – salathe
Rất đẹp, nhưng làm thế nào để có được một đối tượng SplFileInfo cho mỗi tệp, chứ không phải là một đường dẫn đơn giản? –