php列出目录文件

tech2023-11-09  96

php列出目录文件

In this article I’ll talk about a common task you might have experienced while developing a PHP application: listing files and directories. I’ll discuss several basic and advanced solutions, each having its pros and cons. First I’ll present three approaches that use some very basic PHP functions and then progress to more robust ones which make use of SPL Iterators.

在本文中,我将讨论您在开发PHP应用程序时可能会遇到的常见任务:列出文件和目录。 我将讨论几种基本和高级解决方案,每种解决方案都有其优缺点。 首先,我将介绍三种使用一些非常基本PHP函数的方法,然后逐步介绍使用SPL迭代器的更可靠的方法。

For the purposes of the discussion, let’s assume a directory structure that looks like the one below:

为了便于讨论,我们假设一个目录结构如下所示:

---manager | ---user | ---document.txt | ---data.dat | ---style.css |---article.txt |---master.dat |---script.php |---test.dat |---text.txt

基本解决方案 (The Basic Solutions)

The first set of approaches demonstrate the use of the functions glob(), a combination of the functions opendir(), readdir() and closedir(), and the the function scandir().

第一组方法演示了功能glob() ,功能opendir() , readdir()和closedir()以及功能scandir() 。

使用glob() (Using glob())

The first function to discuss is glob() which allows us to perform a search for pathnames using wildcards common to the best known shells. The function has two parameters:

讨论的第一个函数是glob() ,它使我们能够使用众所周知的Shell通用的通配符来搜索路径名。 该函数有两个参数:

$pattern (mandatory): The search pattern

$pattern (强制性):搜索模式

$flags (optional): One or more flags as listed in the official documentation

$flags (可选): 官方文档中列出的一个或多个标志

Let’s see some examples! To search in the directory for all files and directories that end with .txt, you would write:

让我们看一些例子! 要在目录中搜索所有以.txt结尾的文件和目录,应编写:

<?php $filelist = glob("*.txt");

If you display $filelist, the output will be:

如果显示$filelist ,输出将是:

array ( 0 => 'article.txt', 1 => 'text.txt' )

If you want a list of files and directories that begin with “te”, the code to write is:

如果要以“ te”开头的文件和目录的列表,要编写的代码是:

<?php $filelist = glob("te*");

The output is:

输出为:

array ( 0 => 'test.dat', 1 => 'text.txt' )

To get a list of directories only which contain “ma”, the code is:

要获取仅包含“ ma”的目录列表,代码为:

<?php $filelist = glob("*ma*", GLOB_ONLYDIR);

In this last example, the output is:

在最后一个示例中,输出为:

array ( 0 => 'manager' )

Notice that the last example makes use of the GLOB_ONLYDIR constant as the optional second parameter. As you can see, the file called master.dat is excluded because of it. Although the glob() function is easy to use, it isn’t so flexible sometimes. For example, it doesn’t have a flag to retrieve only files (and not directories) that match a given pattern.

请注意,最后一个示例将GLOB_ONLYDIR常量用作可选的第二个参数。 如您所见,由于它,排除了名为master.dat的文件。 尽管glob()函数易于使用,但有时并不那么灵活。 例如,它没有标志来仅检索与给定模式匹配的文件(而不是目录)。

使用opendir()和readdir() (Using opendir() and readdir())

The second approach to read files and directories I’d like to discuss involves the functions opendir(), readdir(), and closedir().

我要讨论的读取文件和目录的第二种方法涉及函数opendir() , readdir()和closedir() 。

opendir() opens the directory and returns a connection handle. Once the handle is retrieved, you can use readdir(). With each invocation, this function will give the name of the next file or directory inside an opened directory. When all the names have been retrieved, the function returns false. To close the handle you use closedir().

opendir()打开目录并返回连接句柄。 一旦检索到句柄,就可以使用readdir() 。 每次调用时,此函数将给出打开目录中下一个文件或目录的名称。 检索到所有名称后,该函数将返回false。 要关闭句柄,请使用closedir() 。

Unlike glob(), this approach is a bit more involved since you don’t have parameters that help you filter the returned files and the directories. You have to perform post-filtering yourself to get what you want.

与glob()不同,此方法要复杂得多,因为您没有可帮助您过滤返回的文件和目录的参数。 您必须自己执行后过滤才能获得所需的内容。

To parallel with the glob() function, the following example retrieves a list of all the files and the directories that start with “te”:

为了与glob()函数并行,以下示例检索所有以“ te”开头的文件和目录的列表:

<?php $filelist = array(); if ($handle = opendir(".")) { while ($entry = readdir($handle)) { if (strpos($entry, "te") === 0) { $filelist[] = $entry; } } closedir($handle); }

The output is the same as the previous example.

输出与前面的示例相同。

But if you execute the code above and output the value of $entry as it runs, you’ll see it contains some odd-looking entries at times: “.” and “..”. These are two virtual directories you’ll find in each directory of the file system. They represent the current directory and the parent directory (the up-level folder) respectively.

但是,如果您执行上面的代码并在运行时输出$entry的值,您会发现它有时包含一些看起来很奇怪的条目:“。” 和“ ..”。 这是两个虚拟目录,您可以在文件系统的每个目录中找到它们。 它们分别代表当前目录和父目录(上级文件夹)。

The second example shows how to retrieve only the files contained in a given path.

第二个示例显示如何仅检索给定路径中包含的文件。

<?php $filelist = array(); if ($handle = opendir(".")) { while ($entry = readdir($handle)) { if (is_file($entry)) { $filelist[] = $entry; } } closedir($handle); }

As you might guess, using the above code produces the following output:

您可能会猜到,使用上面的代码会产生以下输出:

array ( 0 => 'article.txt', 1 => 'master.dat', 2 => 'script.php', 3 => 'test.dat', 4 => 'text.txt' )

使用scandir() (Using scandir())

And finally, I’d like to present the scandir() function. It has only one mandatory parameter: the path to read. The value returned is an array of the files and directories contained in the path. Just like the last solution, to retrieve a subset of files and directories, you have to do post-filtering yourself. On the other hand, as you can see by looking at the code below, this solution is more concise and doesn’t need to manage file handle.

最后,我想介绍一下scandir()函数。 它只有一个强制性参数:读取路径。 返回的值是路径中包含的文件和目录的数组。 就像最后一个解决方案一样,要检索文件和目录的子集,您必须对自己进行后过滤。 另一方面,通过查看下面的代码可以看到,此解决方案更加简洁,不需要管理文件句柄。

This example shows how to retrieve files and directories which start with the string “te”:

此示例显示如何检索以字符串“ te”开头的文件和目录:

<?php $entries = scandir("."); $filelist = array(); foreach($entries as $entry) { if (strpos($entry, "te") === 0) { $filelist[] = $entry; } }

让我们使用SPL迭代器 (Let’s use the SPL Iterators)

Now let’s talk about some SPL Iterators. But before going into deep about their use, let me introduce them and the SPL library. The SPL provides a series of classes for object-oriented data structures, iterators, file handlers, and other features.

现在让我们讨论一些SPL迭代器 。 但是在深入了解它们的用途之前,让我介绍它们和SPL库。 SPL为面向对象的数据结构,迭代器,文件处理程序和其他功能提供了一系列类。

One of the pros is that Iterators are classes and so you can extend them to better fit your needs. Another advantage is that they have native methods that are really helpful in achieving many of the common task you might face and you have them in just one place. Take as an example the use of FilesystemIterator among readdir(), both of them will be used in a loop but while using readdir() your entry will be nothing but a string, using FilesystemIterator you have an object that can provide you a lot of information about that file or directory (size, owner, permissions and so on).

优点之一是Iterators是类,因此您可以扩展它们以更好地满足您的需求。 另一个优点是它们具有本机方法,这些方法对于完成您可能要面对的许多常见任务确实很有帮助,并且只需将它们放在一个位置即可。 举个例子,在readdir()使用FilesystemIterator ,它们都将在循环中使用,但是在使用readdir()您的输入将只不过是一个字符串,而使用FilesystemIterator您将拥有一个可以为您提供很多帮助的对象有关该文件或目录的信息(大小,所有者,权限等)。

Of course, PHP can provide you the same information using functions like filesize() and fileowner() but PHP5 has turned its approach to OOP. So, in conclusion, my advice here is to follow the new best practices for the language. In case you need more general information about SPL Iterators, take a look at Using SPL Iterators.

当然,PHP可以使用filesize()和fileowner()类的功能为您提供相同的信息,但是PHP5已将其方法转换为OOP。 因此,总而言之,我的建议是遵循该语言的新最佳实践。 如果您需要有关SPL迭代器的更多常规信息,请查看使用SPL迭代器 。

As said in the introduction, I’ll show the use of FilesystemIterator, RecursiveDirectoryIterator and GlobIterator. The first of them inherits from the DirectoryIterator while the others inherit from the FilesystemIterator. They all have the same constructor which has just two parameters:

如引言中所述,我将展示FilesystemIterator , RecursiveDirectoryIterator和GlobIterator 。 它们中的第一个从DirectoryIterator继承,而其他的则从FilesystemIterator继承。 它们都具有相同的构造函数,仅有两个参数:

$path (mandatory): The path of the filesystem item to be iterated over

$path (强制性):要迭代的文件系统项的路径

$flags (optional): One or more flags as listed in the official documentation

$flags (可选): 官方文档中列出的一个或多个标志

What actually differs in these iterators is the approach they use to navigate the given path.

这些迭代器的实际区别在于它们用于导航给定路径的方法。

FilesystemIterator (The FilesystemIterator)

Using the FilesystemIterator is quite simple. To see it in action, I’ll show two examples. In the first, I’ll search for all the files and directories which start with the string “te” while the second will use another iterator, the RegexIterator, to search all the files and directories that contains ends with “t.dat” or “t.php”. The RegexIterator is used to filter another iterator based on a regular expression.

使用FilesystemIterator非常简单。 为了看到它的实际效果,我将展示两个示例。 在第一个,我会搜索所有以字符串“TE”,而第二个将使用另一种迭代器,在开始的文件和目录RegexIterator ,搜索所有包含结束与“t.dat”的文件和目录或“ t.php”。 RegexIterator用于基于正则表达式过滤另一个迭代器。

<?php $iterator = new FilesystemIterator("."); $filelist = array(); foreach($iterator as $entry) { if (strpos($entry->getFilename(), "te") === 0) { $filelist[] = $entry->getFilename(); } }

With the code above, the result is the same of the previous examples.

使用上面的代码,结果与前面的示例相同。

The second example that uses the RegexIterator is:

使用RegexIterator的第二个示例是:

<?php $iterator = new FilesystemIterator("."); $filter = new RegexIterator($iterator, '/t.(php|dat)$/'); $filelist = array(); foreach($filter as $entry) { $filelist[] = $entry->getFilename(); }

In this case the output is:

在这种情况下,输出为:

array ( 0 => 'script.php', 1 => 'test.dat' )

RecursiveDirectoryIterator (The RecursiveDirectoryIterator)

The RecursiveDirectoryIterator provides an interface for iterating recursively over filesystem directories. Due to its aim, it has some useful methods as getChildren() and hasChildren() which returns an iterator for the current entry if it is a directory and whether current entry is a directory respectively. To see both RecursiveDirectoryIterator and the getChildren() in action, I’ll rewrite the last example to get the same result.

RecursiveDirectoryIterator提供了用于在文件系统目录上进行递归迭代的接口。 由于其目的,它具有一些有用的方法,例如getChildren()和hasChildren() ,它们分别返回当前条目的迭代器(如果它是目录)和当前条目是否是目录。 为了查看RecursiveDirectoryIterator和getChildren()的实际效果,我将重写最后一个示例以得到相同的结果。

<?php $iterator = new RecursiveDirectoryIterator('.'); $filter = new RegexIterator($iterator->getChildren(), '/t.(php|dat)$/'); $filelist = array(); foreach($filter as $entry) { $filelist[] = $entry->getFilename(); }

GlobIterator (The GlobIterator)

The GlobIterator iterates through the file system in a similar way to the glob() function. So the first parameter can include wildcards. The code below shows the usual example with the use of the GlobIterator.

GlobIterator以类似于glob()函数的方式遍历文件系统。 因此,第一个参数可以包含通配符。 下面的代码显示了使用GlobIterator的通常示例。

<?php $iterator = new GlobIterator("te*"); $filelist = array(); foreach($iterator as $entry) { $filelist[] = $entry->getFilename(); }

结论 (Conclusions)

In this article I’ve illustrated different ways to achieve the same goal: how to retrieve and filter files and directories in a given path. These are some key points to remember:

在本文中,我说明了实现同一目标的不同方法:如何检索和过滤给定路径中的文件和目录。 这些是要记住的一些关键点:

The function glob() is a one-line solution and allows filtering, but it isn’t very flexible.

函数glob()是一种单行解决方案,可以进行过滤,但是它不是很灵活。

The solution using opendir(), readdir(), and closedir() is a bit verbose and needs a post-filtering but is more flexible.

使用opendir() , readdir()和closedir()的解决方案有些冗长,需要后期过滤,但更灵活。

The function scandir() requires post-filtering as well but doesn’t need to manage the handle.

函数scandir()需要后过滤,但不需要管理句柄。

If you want to use an OOP approach, you should use the SPL library. Moreover you can extend the classes to fit your needs.

如果要使用OOP方法,则应使用SPL库。 此外,您可以扩展类以适合您的需求。

While the GlobIterator has the ability to do pre-filtering, the others can do the same in a comfortable way using the RegexIterator.

虽然GlobIterator可以进行预过滤,但是其他人可以使用RegexIterator以舒适的方式进行预过滤。

Do you know of other approaches to achieve the goal? If so and you want to share with us, go ahead. Knowledge sharing is always welcome.

您知道实现目标的其他方法吗? 如果是这样,并且您想与我们分享,请继续。 始终欢迎知识共享。

Image via Fotolia

图片来自Fotolia

翻译自: https://www.sitepoint.com/list-files-and-directories-with-php/

php列出目录文件

最新回复(0)