I have problem with files, for example .342342.jpg or .3423423.ico. The script below dosen't see this files. My script:
<?php
$filepath = recursiveScan('/public_html/');
function recursiveScan($dir) {
$tree = glob(rtrim($dir, '/') . '/*');
if (is_array($tree)) {
foreach($tree as $file) {
if (is_dir($file)) {
//echo $file . '<br/>';
//recursiveScan($file);
} elseif (is_file($file)) {
echo $file . '<br/>';
if (preg_match("[.a-zA-Z0-9]", $file )) {
echo $file . '<br/>';
//unlink($file);
}
}
}
}
}
?>
Use this \.[[:alnum:]]*as your regular expression to match a single dot and then any number of letters and digits afterwards, because as you're using it now it only matches a single character of any kind. Use regex101.com for future regular expression testing. It shows a detailed breakdown of what you're filtering for and has a great cheatsheet for all tokens you can use
AFAIK, glob doesn't return filenames that begin with a dot, so, .342342.jpg is not returned.
Your regex if (preg_match("[.a-zA-Z0-9]", $file )) { matches filenamess that contain .a-zA-Z0-9 (ie. xxx.a-zA-Z0-9yyy) I guess you want filenames that contain dot or alphanum, so your regex becomes:
if (preg_match("/^[.a-zA-Z0-9]+$/", $file )) {
Related
I'm trying to create a script for including (through require_once) multiple files, but I'm expecting from it following behavior:
all file names of required files are defined as values in array
script check if all files from array exist in given directory
if yes, require them and continue (only if each of them exist)
if no, terminate script and show error message (if any file is missing)
UPDATE
After taking a closer look at my original script I found why it didn't work. Second IF statement ($countMissing == 0) was inside FOR loop and it produced empty arrays for files which were found. Taking that IF statement out of the loop sorted the problem.
WORKING VERSION (with few tiny modifications):
// Array with required file names
$files = array('some_file', 'other_file', 'another_file');
// Count how many files is in the array
$count = count($files);
// Eampty array for catching missing files
$missingFiles = array();
for ($i=0; $i < $count; $i++) {
// If filename is in the array and file exist in directory...
if (in_array($files[$i], $files) && file_exists(LIBRARIES . $files[$i] . '.php')) {
// ...update array value with full path to file
$files[$i] = LIBRARIES . $files[$i] . '.php';
} else {
// Add missing file(s) to array
$missingFiles[] = LIBRARIES . $files[$i] . '.php';
}
}
// Count errors
$countMissing = count($missingFiles);
// If there was no missing files...
if ($countMissing == 0) {
foreach ($files as $file) {
// ...include all files
require_once ($file);
}
} else {
// ...otherwise show error message with names of missing files
echo "File(s): " . implode(", ", $missingFiles) . " wasn't found.";
}
If this thread won't be deleted I hope it will help somebody.
Try this:
$files = array(
'some_file',
'other_file',
'another_file',
);
// create full paths
$files = array_map(function ($file) {
return ROOT_DIR . $file . '.php')
}, $files);
// find missing files
$missing = array_filter($files, function ($file) {
return !file_exists($file);
});
if (0 === count($missing)) {
array_walk($files, function ($file) {
require_once $file;
});
} else {
array_walk($missing, function ($file) {
echo "File: " . $file " wasn't found.";
});
}
For reference, see:
http://php.net/manual/en/function.array-map.php
http://php.net/manual/en/function.array-filter.php
http://php.net/manual/en/function.array-walk.php
Try this, prevent loop inside the loop.
for ($i=0; $i < $count; $i++) {
// If filename is in the array but file not exist in directory...
if (in_array($files[$i], $files) && !file_exists(ROOT_DIR . $files[$i] . '.php')) {
// ...add name of missing file to error array
$errors[] = $files[$i];
}
else{
require_once (ROOT_DIR . $file[$i] . '.php');
}
}
The code from localheinz and jp might be fine, but I wouldn't code things like that because it makes things complicated. Assuming you don't want a list of missing files (which would be slightly different) I'd do it like this:
$filesOK=true;
foreach($files as $file)
{
$path = ROOT_DIR . $file . ".php";
if(!file_exists($path ))
{
$filesOK=false; // we have a MIA
break; // quit the loop, one failure is enough
}
}
if($filesOK)
foreach($files as $file)
require_once($file);
else
echo "We have a problem";
For me this is much easier to see at a glance. Easier to debug, and the CPU is going to do the same job one way or anther. Probably not much difference in execution speed - if that even mattered.
If you need the list of missing files, then:
$filesOK=true;
foreach($files as $file)
{
$path = ROOT_DIR . $file . ".php";
if(!file_exists($path)) // assume each file is given with proper path
{
$filesOK=false; // we have a MIA
$mia[]=$path; // or $file if you just want the name
}
}
if($filesOK)
foreach($files as $file)
require_once($file);
else
{
if(is_array(#$mia)) // I always make sure foreach is protected
foreach($mia as $badfile) // even if it seems obvious that its ok
echo "Missing in action: $badfile<br>";
}
I need to check if $string exists in one of the files in a folder. Below is what I have, but it's obviously not working. What am I missing?
foreach (glob($path . 'foo/bar/*.*') as $file) {
if (strpos(file_get_contents($file), $string) !== false) {
//** found
} else {
//** not found
}
}
Are you sure all your files include an extension? You could try
glob($path . 'foo/bar/*')
and see if that works.
Also, if you're using Windows you should use a backslash (\) instead of a forward slash (/). You could use the DIRECTORY_SEPARATOR constant to let PHP automate it for you.
glob($path . 'foo' . DIRECTORY_SEPARATOR . 'bar' . DIRECTORY_SEPARATOR . '*.*')
Are you also sure that $path ends with a slash?
I am trying to use regex pattern to search for files.
Directory path is:
$css_dir = MY_PLUGIN_DIR.'/source/css/';
Css filename starts with:
$css_prefix = 'hap_css_';
and ends with:
'.css'
With some amount of unknown characters in between.
I dont know how to construct regex pattern with variable and how to construct file exist with regex.
Thank you!
You can use glob():
$files = glob($css_dir . $css_prefix . '*.css');
However, you have to roll your own DirectoryIterator based solution for more complex filtering:
$dir = new DirectoryIterator($css_dir);
$pattern = '/^' . preg_quote($css_prefix) . '.+\\.css$' . '/';
foreach ($dir as $fileInfo) {
if (preg_match($pattern, $fileInfo->getBaseName())) {
// match!
}
}
(One could also integrate a RegexIterator):
The use of scandir() is possible as well:
$pattern = '/^' . preq_quote($css_prefix) . '.+\\.css$' . '/';
$files = array_filter(scandir($css_dir), function ($filename) {
return preg_match($pattern, $filename);
});
I have one main directory "Images" and many subdirectories - inside them are files (in main folder too). Example tree:
+Images
-first.jpg
-second.jpg
++FOLDER1
--image1.jpg
++FOLDER2
--image2.jpg
I found a script there:
function ListFiles($dir) {
if($dh = opendir($dir)) {
$files = Array();
$inner_files = Array();
while($file = readdir($dh)) {
if($file != "." && $file != ".." && $file[0] != '.') {
if(is_dir($dir . "/" . $file)) {
$inner_files = ListFiles($dir . "/" . $file);
if(is_array($inner_files)) $files = array_merge($files, $inner_files);
} else {
array_push($files, $dir . "/" . $file);
}
}
}
closedir($dh);
return $files;
}
}
$list = ListFiles('../upload/_thumbs/Images');
sort($list);
foreach ($list as $key=>$file){
echo '<option value="">'.$file.'</option>';
}
This script works fine but I can sort my results by folders (first main content, then rest)... I get i my select:
../upload/_thumbs/Images/first.jpg
../upload/_thumbs/Images/FOLDER1/image1.jpg
../upload/_thumbs/Images/FOLDER2/image2.jpg
../upload/_thumbs/Images/second.jpg
Expection:
../upload/_thumbs/Images/first.jpg
../upload/_thumbs/Images/second.jpg
../upload/_thumbs/Images/FOLDER1/image1.jpg
../upload/_thumbs/Images/FOLDER2/image2.jpg
I would be glad if you will help me! Thanks!
Well it probably has something to do with the sort function you call somewhere in the last lines
sort($list);
It's causing the array to sort alphabetical. You could try to leave it out, or you could try to use natsort.
natsort($list);
This is happening because you are sorting with the full path. Instead of sort, I would use uasort which is similar to sort, except you use a callback function to define which goes first.
alternatively, you could get by prepending the file name to the path and using the key on insert. In other words:
array_push($files, $dir . "/" . $file);
becomes:
$files[$file . $dir] = $dir . "/" . $file;
then you sort using ksort
I have a text file in the same folder as the script I'm trying to run. It has several URL links each on a new line like so:
hxxp://www.example.com/example1/a.doc
hxxp://www.example.com/example2/b.xls
hxxp://www.example.com/example3/c.ppt
I'm trying to link these files but it only lists the last file in the list.
Here is my code:
<?php
$getLinks = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/links.txt');
$files = explode("\n", $getLinks);
foreach ($files as $file) {
if (substr($file, 0, 23) == 'hxxp://www.example.com/') {
$ext = pathinfo(strtolower($file));
$linkFile = basename(rawurldecode($file));
if ($ext['extension'] == 'doc') {
echo '<img src="images/word.png" /> ' . $linkFile . '<br />';
} elseif ($ext['extension'] == 'xls') {
echo '<img src="images/excel.png" /> ' . $linkFile . '<br />';
} elseif ($ext['extension'] == 'ppt') {
echo '<img src="images/powerpoint.png" /> ' . $linkFile . '<br />';
}
}
}
?>
*note: I've tried using the file function as well with the same results.
You can improve this code in many ways:
Use file instead of file_get_contents to have the lines put into an array automatically
Use strpos instead of substr -- more efficient
Use strrpos to get the file extension -- faster and foolproof, as know exactly how it behaves
You should be using rawurlencode instead of rawurldecode because you are creating urls, not reading them
The if conditionals for the extensions should be replaced by an array lookup
Making all these changes, we have:
$lines = file($_SERVER['DOCUMENT_ROOT'] . '/links.txt');
$extensions = array(
'doc' => 'word.png',
'xls' => 'excel.png',
'ppt' => 'powerpoint.png',
);
foreach ($lines as $file) {
if (strpos($file, 'hxxp://www.example.com/') !== 0) {
continue;
}
$ext = strtolower(substr($file, strrpos($file, '.') + 1));
if (empty($extensions[$ext])) {
continue;
}
printf('<img src="images/%s" /> %s<br />',
$file, $extensions[$ext], rawurlencode(basename($file)));
}
$getLinks = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/links.txt');
$files = explode("\r\n", $getLinks);
I'm assuming you're on windows, the same as me.
\n isn't the whole windows new line character Use \r\n
When I replaced \n with \r\n it worked as expected