09.09.2024
Home / Game consoles / Php get the last added file in subfolders. Getting a list of files and directories using PHP. Using SPL Iterators

Php get the last added file in subfolders. Getting a list of files and directories using PHP. Using SPL Iterators

In this lesson we will deal with a typical task that arises while working on a PHP project: getting a list of files and directories. We will discuss several basic and more sophisticated approaches, listing the pros and cons of each. The first three solutions will use standard PHP functions, and then we will present a more robust one using SPL iterators.

For substantive discussion of the solution and demonstrations, we will assume that the directory structure is as follows:

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

Basic solutions

The first set of solutions is based on using the glob() function, a combination of the opendir() , readdir() and closedir() functions, and also the scandir() function.

Using glob()

The first solution is based on using the glob() function, which allows you to search for paths using patterns. The function has two parameters:

  • $pattern (required): search pattern
  • $flags (optional): one or more flags, descriptions of which can be found in the documentation

Let's look at examples. To search a directory for all files and directories whose names end with .txt, you should use the code:

If we display the $filelist variable, we get:

Array (0 => "article.txt", 1 => "text.txt")

If you need a list of files and directories whose names begin with “te”, then the code will look like this:

And the output looks like:

Array (0 => "test.dat", 1 => "text.txt")

And to get a list of only directories with names containing “ma”, use the code:

The last example will output:

Array (0 => "manager")

Note that the last example uses the GLOB_ONLYDIR flag as the second parameter of the function. Therefore, the master.dat file is excluded from the list. Although the glob() function is very easy to use, sometimes it is not flexible enough. For example, there is no flag to get only files (no directories) that match the pattern.

We use opendir() , readdir() , and closedir() .

The second approach to obtaining a list of files and directories that we will discuss is to use the opendir() , readdir() , and closedir() functions.

The opendir() function opens a directory and returns a connection handle. Once the handle is obtained, the readdir() function can be used. With each call, this function returns the name of the next file or directory within the open directory. If all names have already been listed, the function returns false. The closedir() function is used to close the handle.

Unlike using the glob() function, this approach is more complex because you don't have parameters to help filter the list of file and directory names that are returned. You must do the filtering yourself to get the results you want.

The following example returns a list of file and directory names starting with “te”:

When you run the above code, the $entry variable will contain inclusions such as “.” And "..". These are two virtual directories that exist in each directory file system. They represent the current directory and parent directory respectively.

The second example displays only the files contained in the given directory.

The example will produce the following:

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

Using scandir()

Finally, let's introduce the scandir() function. It has only one required parameter: the reading path. The function returns an array of files and directories located at the specified path. To obtain a list of files and directories based on a specific criterion, you need to perform additional filtering. On the other hand, the solution is more concise and does not require handle management.

This example shows how to get a list of files and directories whose names begin with “te”:

Let's use SPL iterators

Now let's look at using SPL iterators. But before we begin solving our problem, let's give an introduction to the SPL library and iterators. The SPL library provides a series of classes for object-oriented data structures, iterators, file descriptors, and more.

One of the benefits of iterators is that they are classes and can be extended to suit your own needs. Another advantage is that iterators have their own methods, which are useful for solving many common problems and are located in one place. Look at an example of using FilesystemIterator versus readdir() . Both methods use a loop, but with readdir() you only process a string, while FilesystemIterator works with an object that can contain additional information about the file or directory (size, owner, permissions, and so on).

Of course, PHP provides the ability to obtain such information using functions such as filesize() and fileowner(). But PHP5 is based on using OOP concept. Therefore it is better to use modern methods working with a programming language. There are lessons on working with iterators on our website.

As already stated in the watery part of the tutorial, we will cover the use of FilesystemIterator, RecursiveDirectoryIterator and GlobIterator. The first one inherits from DirectoryIterator and the rest from FilesystemIterator . They all have the same constructor, which takes two parameters:

  • $path (required): path to the file system entry on which operations are performed
  • $flags (optional): one or more flags listed in the documentation

The real difference in these iterators is how they are used to navigate along a given path.

FilesystemIterator

Using FilesystemIterator is very simple. Let's see it in action. We present two examples. The first one shows a search for all files and directories whose names begin with “te”. The second example uses another RegexIterator to find all files and directories whose names end with “t.dat” or “t.php”. The RegexIterator is used to filter the result based on regular expressions.

getFilename(), "te") === 0) ( $filelist = $entry->getFilename(); ) )

The above code will produce a result similar to the previous examples.

Second example using RegexIterator:

getFilename(); )

It will output:

Array (0 => "script.php", 1 => "test.dat")

RecursiveDirectoryIterator

The RecursiveDirectoryIterator provides an interface for recursively traversing file system directories. It has several useful methods, such as getChildren() and hasChildren(), which return an iterator for the current location if it is a directory, and check whether the current entry point is a directory. The following example demonstrates the use of RecursiveDirectoryIterator and getChildren() . The result will be the same as in the previous examples.

getChildren(), "/t\.(php|dat)$/"); $filelist = array(); foreach($filter as $entry) ( $filelist = $entry->getFilename(); )

GlobIterator

The GlobIterator iterates through the file system in the same way as the glob() function. The first parameter may include a pattern for the name. The example demonstrates the use of GlobIterator with the same result as before.

getFilename(); )

Conclusion

This lesson demonstrates the use of different approaches to achieve the same goal: obtaining a list of files and directories. The following key points should be remembered:

  • The glob() function is a built-in solution, but it is not flexible enough.
  • A solution based on opendir() , readdir() , and closedir() is more complex and requires additional filtering, but it is more flexible.
  • The scandir() function requires additional filtering, but works without processing the handle.
  • If you are using an OOP approach, then you should use the SPL library. Additionally, you can extend classes with your own functionality.
  • The GlobIterator has a pre-filtering feature, while others use RegexIterator.

Reg.ru: domains and hosting

The largest registrar and hosting provider in Russia.

More than 2 million domain names in service.

Promotion, domain mail, business solutions.

More than 700 thousand customers around the world have already made their choice.

*Mouse over to pause scrolling.

Back Forward

Getting a list of folders using PHP

Listing directories using PHP, or listing directories

We will call directory listing a general query that generates a list of all or some files and directories of the parent directory - a process similar to the work of the index page provided by most web servers, but with O greater control over the content and formatting of the same.

Another advantage of this script is the ability to perform certain actions with files using PHP. In any case, the first step we need to do is query the file system - return a list of files and directories.

The functions presented below allow you to extract file names and other properties from a specific directory, or iterate through subcategories recursively.

Comment: PHP5 has a function scandir, which “returns a list of files and directories inside a directory at a given path,” but it does not display any additional information about the files inside the directory.

Listing one directory

To begin with, here is an example of a simple function that returns a list of files, directories and their properties from one directory (you will find more advanced versions of this function a little later in this lesson.)

read())) ( // skip hidden files if($entry == ".") continue; if(is_dir("$dir$entry")) ( $retval = array("name" => "$dir$ entry/", "size" => 0, "lastmod" => filemtime("$dir$entry")); ) elseif(is_readable("$dir$entry")) ( $retval = array("name" = > "$dir$entry", "size" => filesize("$dir$entry"), "lastmod" => filemtime("$dir$entry") ) ) $d->close(); return $retval; ) ?>

You can use this function like below:

The return value is an associative array of files, including the file's path information, size, and last modification date, unless the file is a directory, in which case the string "(dir)" appears instead of the file size.

Example 1:

",print_r($dirlist),""; /* example output Array ( => Array ( => images/background0.jpg => image/jpeg => 86920 => 1077461701) => ...) */ ?>

Example 2:

",print_r($dirlist),""; /* example output Array ( => Array ( => ./images/background0.jpg => image/jpeg => 86920 => 1077461701) => ...) */ ?>

Listing files via HTML

To get the output results on the page in HTML, we'll loop through the returned array

\n"; echo " NameTypeSizeLast Mod.\n"; foreach($dirlist as $file) ( echo " \n"; echo " ($file["name"])\n"; echo " ($file["type"])\n"; echo " ($file["size"])\n"; echo " \n"; echo "\n"; ) echo "\n\n"; ?>

This code is quite easy to modify, for example:

  • - display the listing results as a list instead of a table;
  • - make file names active links;
  • - replace names with icons based on what type of file it is;
  • etc.

For example, to output only PNG files, add a simple condition to the output loop:

\n"; echo " NameTypeSizeLast Mod.\n"; foreach($dirlist as $file) ( //check if the file is a PNG if(!preg_match("/\.png$/", $file["name"])) continue; echo " \n"; echo " ($file["name"])\n"; echo " ($file["type"])\n"; echo " ($file["size"])\n"; echo " ",date("r", $file["lastmod"]),"\n"; echo "\n"; ) echo "\n\n"; ?>

This example will skip and hide all files whose names end with .png. You can also apply additional conditions based on the file type, size, or date it was last modified.

If you, for example, want to display a thumbnail, a link to a larger picture, or even a video, just give these 2 files the same names and in the script above use str_replace or similar function to modify the content of links.

Recursive directory listing

And since we've come this far, there will only be minor changes to the recursive list and subcategory calling function. By adding a second parameter to the function, we retain the previous functionality of listing a single directory.

read())) ( // skip hidden files if($entry == ".") continue; if(is_dir("$dir$entry")) ( $retval = array("name" => "$dir$ entry/", "size" => 0, "lastmod" => filemtime("$dir$entry")); if($recurse && is_readable("$dir$entry/")) ( $retval = array_merge($ retval, getFileList("$dir$entry/", true) ) elseif(is_readable("$dir$entry")) ( $retval = array("name" => "$dir$entry", "size " => filesize("$dir$entry"), "lastmod" => filemtime("$dir$entry")); ) ) $d->close(); return $retval; ) ?>

For the new functionality to work, you need to enter a value true(or 1) as the second parameter.

Before recursing the script, check whether the subdirectories are readable and also read the last paragraph of this lesson in order to avoid access errors.

As before, the return value is an array, an associative array. In fact, the only addition is another additional option for recursive listing.

Recursion Depth Limit

This final example adds one more feature - the ability to specify how "deep" the recursion should go. The previous code will continue to explore subdirectories until they run out. This script will help you set a limit on the number of levels of nested directories.

read())) ( // skip hidden files if($entry == ".") continue; if(is_dir("$dir$entry")) ( $retval = array("name" => "$dir$ entry/", "size" => 0, "lastmod" => filemtime("$dir$entry")); if($recurse && is_readable("$dir$entry/")) ( if($depth == = false) ( $retval = array_merge($retval, getFileList("$dir$entry/", true)); ) elseif($depth > 0) ( $retval = array_merge($retval, getFileList("$dir$entry /", true, $depth-1)); ) ) ) elseif(is_readable("$dir$entry")) ( $retval = array("name" => "$dir$entry", "size" => filesize("$dir$entry"), "lastmod" => filemtime("$dir$entry") ) ) $d->close(); return $retval; ) ?>

As before, we added only 1 new parameter and a couple of lines of code. If the default value responsible for the recursion depth is not specified, then it is set to false. This allows us to be sure that previous features remain and subsequent code will not “break” when the function changes.

Working with files

The need for operations with files confronts the programmer very often. If your scripts do not use databases, then files are the only acceptable storage devices for the script. The use of files as repositories of script execution information allows them to be used in a wide variety of situations. Almost all counter scripts for something are written based on working with files. It is also possible to give a bunch of other examples, but it’s time to move directly from words to action.

I want to say right away that working with the file must be authorized. By default, PHP does not allow file manipulation for security reasons. To remove this ban in the CuteFTP FTP manager, check all the boxes in the file properties; other managers should have something similar.

file_exists

Before you perform operations on a file, you often need to make sure that the specified file even exists. This is what the file_exists function does. This function can only return two values, as you can imagine TRUE(if the specified file exists) and FALSE. Typically, using this function looks like this:

Please note that the function only works on local files, that is, if you want to check whether Yandex has acquired a robot.txt file, then your efforts will be in vain. But it is possible to check any file located on the local server, regardless of the directory of its location.

Here are some rules for describing the path to a file.

filesize

As the name suggests, the function determines the file size and returns it in bytes. Useful if you want to check a file to see if it contains information (as you might imagine, an empty file contains 0 bytes), and it is also possible to check the file size to see if it exceeds a certain limit.

file

This function already works directly with the file. It returns the contents of the specified file, and it does this in the form of an array, where each element is a line of the file. The function is useful when you need to store several different values ​​in one file that should not intersect. Then each value is stored on a separate line and read by the file function, which returns an array, whereby the given variable is accessed by reading the value of the array element with the index corresponding to the line in the file.

It is also possible to reunite all elements of the returned array into a single variable. This is done using the implode array function.

fopen

If the previous function is self-contained and generally not related to other functions, then subsequent functions for working with files work in conjunction with fopen . This function opens the specified file and returns the file connection identifier, which is used for service purposes. This function is in no way associated with the contents of the file.

The fopen function has several modes for working with a file. They are indicated after the file name and are as follows:

    "r"
    The file is opened for reading its contents only.

    "r+"
    Opening a file for both reading and writing.

    "w"
    The file is opened for writing purposes.

    "w+"
    Open the file for reading and writing.

    "a"
    The file is opened for writing to the end of the file (append).

    "a+"
    Opens for further writing and reading.

fgets

Function for reading a file opened by the fopen function. But unlike file, this function returns only one line of the file each time it is executed, and it moves the internal file pointer to the next line, which it will read the next time the function is called. Therefore, if you need to read the entire file, you must use this function in a loop.

Note that the fgets function uses an additional length parameter, which specifies the maximum length of a file line to read. If the size of the string exceeds this number, then the function will return it in a “truncated” form with a length of bytes. By default, this parameter is set to 1024 bytes, or one kilobyte. Especially pay attention to this parameter if you use large files, since when reading such files, the PHP execution buffer may overflow (its size is indicated in the configuration file), which will lead to a freeze.

Please note that the file to read is not the file name, but the file connection identifier returned by the fopen function (in our example, the value of the $file variable).

fputs

The function of writing information to a file, and it does this according to the principle of the fgets function, that is, it starts writing from the position of the internal file pointer. In general, this function is in many ways similar to the above: it also uses the write data length parameter, which is also optional.

fclose

As you might have guessed, this function closes the specified file. Actually, upon completion of the script, PHP itself closes all open files, but it is still better to do this manually. As a function parameter, you must specify the file connection identifier.

To illustrate the combination of the above functions, we will give an example of creating a simple visit counter.

$file = fopen("counter.txt", "r");
$c = fgets($file, 150);
fclose($file);
$c++;
$file = fopen("counter.txt", "w");
fputs($file, $c);
fclose($file);
echo $c;
?>

Working with directories

Closely related to actions on files are operations on directories. The algorithm for working with them is similar to operations on files: first you need to open the directory, perform some actions and, finally, close it.

opendir

This function opens the specified directory and returns the service identifier for the directory connection. Directory paths should be specified as follows:

The dot means opening the current directory

. /files/

Opening a folder files located in the current directory

Opening a folder one level higher than the current one

readdir

The function reads the directory opened by opendir . For each pass, it returns the name of the file or folder located in the specified directory and moves the internal pointer to the next directory object. So to read the entire directory it must be used in a loop.

It should also be noted that this function returns folder service objects . And .. , which can be trimmed when output by the IF statement.

closedir

We close the directory, specifying the folder connection identifier as an argument.

Sometimes using directory functions makes life a lot easier. For example, in the Features section, you can see a list of features in alphabetical order. Can you imagine how much time it would take to manually write this entire list with links, and even in alphabetical order. And this is where the functions for working with directories helped me. Each function was placed in a separate file with a name corresponding to the name of the function, without any extensions.

So, every time you visit the page, you get a newly generated list of functions.

That's all. See you in the next lesson.

Directory listing is the process of obtaining information about directories and files for a given parent directory, as well as the ability to apply various filters to this data to correct the output.

In this example, we will try to cope with a typical task that appears in almost every PHP project - obtaining a list of directories and/or files. The example uses several basic and more complex approaches, outlining the pros and cons of each technique. The first three solutions use standard PHP functions. The latest more reliable solution using PHP SPL iterators.


For a more visual representation, we use a directory structure that looks like this:


\-Application | \-User | \-data.apk | \-style.css | \-test.txt |-readme.txt |-script.php |-serial.txt |-test.html |-test.js

Basic solutions
The first set of examples uses functions glob() and combinations of functions opendir(), readdir(), closedir(), as well as the function scandir().

Using glob()

Usage example php functions glob(), which allows you to search for a path using a pattern.
Function glob( $pattern,$flags) operates with two arguments:
  • $pattern(required): search pattern string
  • $flags
    • GLOB_MARK- Adds a slash to each returned directory.
    • GLOB_NOSORT- Returns files in the form in which they are contained in the directory (without sorting). If this flag is not specified, then names are sorted alphabetically.
    • GLOB_NOCHECK- Returns a search pattern if no files were found using it.
    • GLOB_NOESCAPE- Backslashes do not escape meta characters.
    • GLOB_BRACE- Expands (a,b,c) to match "a", "b" or "c".
    • GLOB_ONLYDIR- Returns only directories matching the pattern.
    • GLOB_ERR- Stops on read errors (for example, directories without read permission), by default errors are ignored.
To search a directory for all files and directories whose names end in .txt, use the following code:In the output we get the following result: array(2) ( => string(10) "readme.txt" => string(10) "serial.txt" ) If you need to get a list of files and directories whose names begin with "te":In the output we get the following result: array(2) ( => string(9) "test.html" => string(7) "test.js" ) Getting only directories with names containing "er" in the list:In the output we get the following result: array(1) ( => string(4) "User" )

The last example uses the flag GLOB_ONLYDIR as the second argument to the function. Therefore, only the “User” directory in the name, which contains “er,” was included in the list. The glob() function is very easy to use, but sometimes it is not flexible enough. There is no flag to get only files (no directories) that match the pattern.

Using opendir(), readdir(), and closedir().

The next method for getting a list of files and directories is to use PHP functions opendir(), readdir() And closedir().

Function opendir() returns a handle to the open directory. Once the handle is received, you can use the function readdir(). When accessing a handle, the function readdir() displays the name of the next file or directory. If all elements contained in the descriptor have already been enumerated, the function readdir() will return false. To close the descriptor we use the function closedir().


Unlike using php function , this approach is a little more complicated. It is not possible to set filtering parameters that help to generate a list of returned file and directory names in advance. To obtain the required list of files and directories, filtering must be performed independently.


The following example returns a list of file and directory names starting with "Us":The output will be: array(1) ( => string(4) "User" ) The following example will output only the files contained in the given directory.In the output we get the following result: array(5) ( => string(10) "script.php" => string(7) "test.js" => string(9) "test.html" => string(10) "serial.txt" => string(10) "readme.txt" )

Using scandir().

To finish, let's look at an example of using a php function scandir(). It has only one required attribute - the path to the reading directory. The result of the function is an array of files and directories located along the path specified in the argument. As in the previous example, to obtain a filtered list of files and directories, you must run it yourself. Visually, the solution is shorter and no descriptor management is required.


The example shows how to get a list of files and directories whose names begin with "te":In the output we get the following result: array(2) ( => string(9) "test.html" => string(7) "test.js" )

Advanced solution using PHP SPL
More reliable solution using SPL iterators FilesystemIterator, RecursiveDirectoryIterator And GlobIterator.

Using SPL iterators.

Let's look at using SPL iterators. Before we begin solving the problem, let's get acquainted a little with the PHP SPL library and iterators. The SPL library provides specialized sets of classes for object-oriented data structures, iterators, file descriptors, and more.


The main advantage of iterators is that they are classes and can be extended using a standard mechanism php inheritance classes. Another plus is that iterators have their own methods that can be useful for solving common problems, and they are all located in one place. Let's look at an example of use FilesystemIterator and compare with readdir(). Both methods use a loop, but in case readdir() it will be possible to process only the string, but FilesystemIterator can work with an object. Which may contain additional information about the file or directory such as owner, size, access rights, and so on.


Of course, PHP has the ability to obtain this information using functions, filesize(), fileowner() and others. But PHP, like any programming language, has the ability to change. In PHP5 there is an increasing desire to use OOP concepts. Therefore, it is better to use modern methods of working with a programming language.


Consider using FilesystemIterator, RecursiveDirectoryIterator And GlobIterator. The first iterator is inherited from DirectoryIterator, and the rest from FilesystemIterator. They all have the same constructor, which takes two arguments:

  • $path(mandatory): path to the file system item on which operations are performed
  • $flags(optional): one or more flags
    • FilesystemIterator::CURRENT_AS_PATHNAME Causes the FilesystemIterator::current() method to return a path.
    • FilesystemIterator::CURRENT_AS_FILEINFO Causes the FilesystemIterator::current() method to return an instance of SplFileInfo.
    • FilesystemIterator::CURRENT_AS_SELF Causes the FilesystemIterator::current() method to return $this (FilesystemIterator).
    • FilesystemIterator::CURRENT_MODE_MASK Masks FilesystemIterator::current()
    • FilesystemIterator::KEY_AS_PATHNAME Causes the FilesystemIterator::key() method to return a path.
    • FilesystemIterator::KEY_AS_FILENAME Causes the FilesystemIterator::key() method to return the file name.
    • FilesystemIterator::FOLLOW_SYMLINKS Forces the RecursiveDirectoryIterator::hasChildren() method to follow symbolic links.
    • FilesystemIterator::KEY_MODE_MASK Masks FilesystemIterator::key()
    • FilesystemIterator::NEW_CURRENT_AND_KEY Same as FilesystemIterator::KEY_AS_FILENAME | FilesystemIterator::CURRENT_AS_FILEINFO.
    • FilesystemIterator::SKIP_DOTS Skips dot files (. and ..).
    • FilesystemIterator::UNIX_PATHS Forces all paths to use Unix-style backslashes, regardless of system default settings.

The difference in these iterators is how they are used to navigate along a given path.

FilesystemIterator

Use FilesystemIterator very simple.
The example shows a search for all files and directories whose names begin with "te".

getFilename(),"te")===0): $arFileList = $obFile->getFilename(); endif; endforeach; //Display the result var_dump($arFileList); ?> In the output we get the following result: array(2) ( => string(7) "test.js" => string(9) "test.html" )

Example of using another iterator RegexIterator to search for all files and directories whose names end with "t.js" or "t.php". Iterator RegexIterator is used to filter the result and uses a regular expression engine.

getFilename(); endforeach; //Display the result var_dump($arFileList); ?> In the output we get the following result: array(2) ( => string(10) "script.php" => string(7) "test.js" )

RecursiveDirectoryIterator

Iterator RecursiveDirectoryIterator provides an interface for recursively traversing file system directories. It has several useful methods such as getChildren() And hasChildren(), which return an iterator for the current location if it is a directory, and check whether the current entry point is a directory.


RecursiveDirectoryIterator And getChildren(). getChildren(), "/t\.(txt|css)$/"); $arFileList = array(); foreach($rxIterator as $obFile): $arFileList = $obFile->getFilename(); endforeach; //Display the result var_dump($arFileList); ?> In the output we get the following result: in this case- this is a file from the "User" directory: array(1) ( => string(8) "test.txt" )

GlobIterator

Iterator GlobIterator performs a file traversal similar to the . The first attribute may include a name pattern.


The example demonstrates the use GlobIterator with the same result as before.getFilename(); endforeach; //Display the result var_dump($arFileList); ?> In the output we get the following result: array(2) ( => string(10) "/test.html" => string(8) "/test.js" )

Conclusion

The examples above were considered various methods PHP to achieve the same goal: getting a list of files and directories.

The following main points can be highlighted from the examples: