With geriatric Internet Explorer versions this site looks shite. This because Impossiblue is built with modern tools and would require hacks and workarounds to function in legacy browsers. I no longer have the patience nor the inclination to satisfy everybody. Impossiblue is an experiment and a playground – and my sustenance does not depend on it. As a concequence – to embarrass nobody – I have decided to lock you out. So, there.

Impossiblue

PHP – How to find pathnames matching a pattern

First published on Ka of Isis 140420

Note: As github.io (where this website lives) does not support PHP, the results shown in this article, are simulations.

According to the PHP manual, the glob() function searches for all the pathnames matching a pattern and returns an array containing the matched files/directories, an empty array if no file matched, or false on error. As an example, the following code will search for – and build an array of – text files in a given directory and display file names and their corresponding file sizes concatenated on separate lines:

foreach (glob("*.txt") as $filename) {
	echo "$filename (" . filesize($filename) . " bytes)<br>";
}

Testing this live with three plain text files stored in the same directory as this article is stored, the result is:

file-1.txt (136 bytes)
file-2.txt (262 bytes)
file-3.txt (1668 bytes)

On some systems, however, it is impossible to distinguish between an empty match and an error. If no matching files are found, either nothing will be displayed or a message will be generated. In a comment to the PHP manual, an anonymous user states that the glob function result will only be an array if it finds some files, and the foreach statement requires its argument to be an array. By checking for the possibility that the result of the glob function may not be an array, the warning can be eliminated.

He/she suggests a modified script:

$matches = glob("*.txt");
if (is_array ($matches)) {
	foreach ($matches as $filename) {
		echo "$filename (" . filesize($filename) . " bytes)<br>";
	}
}

Applying the same test as above, an ideal result is (once more):

file-1.txt (136 bytes)
file-2.txt (262 bytes)
file-3.txt (1668 bytes)

So, how many matching files are there?

$matches = glob("*.txt"); // Assuming the same directory. Otherwise: ("/sub1/sub2/sub3/*.txt")
if (is_array ($matches)) {
	echo "There are " . count($matches) . " plain text files in the directory";
} else {
	echo 0; // Note that this does not explain possible error messages
}

The script above should echo the number of matching files in the directory:

There are 3 plain text files in the directory

Now, pick a random text file from an array of matching files and display the first 12 characters

$matches = glob("*.txt");
if (is_array ($matches)) {
	$rndm = rand(1, count($matches));
	$filename = "file-" . $rndm . ".txt";
	$handle = fopen($filename, "r");
	$text = fread($handle, 12); // 12 bytes equals 12 characters. Note that we assume here that the file is at least that long
	fclose($handle);
	echo "The randomly selected file is " . $filename . " and the initial text is: " . $text . "…";
}

The randomly selected file is file-3.txt and the initial text is: At vero eos …

Note: This example does not check whether the file is at least 12 characters (bytes) long.

Finally, pick a random text file from an array of matching files and display the whole text

1st Approach

$matches = glob("*.txt");
if (is_array ($matches)) {
	$rndm = rand(1, count($matches));
	$filename = "file-" . $rndm . ".txt";
	$handle = fopen($filename, "r");
	$text = fread($handle, filesize($filename)); // This returns ALL of the text if bytes are not specified
	fclose($handle);
	echo "The randomly selected file is " . $filename . " and the contents are as follows: " . $text;
}

The randomly selected file is file-1.txt and the contents are as follows: Lorem ipsum dolor sit amet, consectetur adipscing elit, sed diam nonnumy tempor incidunt ut labore et dolore magna aliquam erat volupat.

2nd Approach

When the goal is to get the complete contents of a file into a string, file_get_contents() has a better performance than the 1st approach:

$matches = glob("*.txt");
if (is_array ($matches)) {
	$rndm = rand(1, count($matches));
	$filename = "file-" . $rndm . ".txt";
	$text = file_get_contents($filename);
	echo "The randomly selected file is " . $filename . " and the contents are as follows: " . $text;
}

The randomly selected file is file-1.txt and the contents are as follows: Lorem ipsum dolor sit amet, consectetur adipscing elit, sed diam nonnumy tempor incidunt ut labore et dolore magna aliquam erat volupat.