Finding broken symlinks using php - php

I'm writing a build/deploy script using a CLI php script.
Say I have a directory /environment and in it there are simply two broken symlinks.
I'm running glob(/environment/{,.}*). When I foreach over the glob, all I see are . and ... The symlinks never show up in the list.
How can you loop over a directory, detect broken symlinks, and unlink() them using PHP?

On a broken symlink is_link() returns true and file_exists() returns false.
Since glob() does not list broken symlinks, you have to list the contents in a different way.
Here is an example using scandir()
foreach(scandir($dir) as $entry) {
$path = $dir . DIRECTORY_SEPARATOR . $entry;
if (is_link($path) && !file_exists($path)) {
#unlink($path);
}
}

use realpath function:
foreach(scandir($dir) as $entry) {
$path = $dir . DIRECTORY_SEPARATOR . $entry;
if (!realpath($path)) {
#unlink($path);
}
}

Related

How to detect folders names in a directory usinig php?

I need php to detect folder names in a directory on my computer not in the project directory in wamp server. i tried all the answers on
Using scandir() to find folders in a directory (PHP)
but it didn't work
it says the directory is not on the project directory when i tested scandir as in this code:
$path = 'extracted/' . $name[0];
$results = scandir($path);
foreach ($results as $result) {
if ($result === '.' or $result === '..') continue;
if (is_dir($path . '/' . $result)) {
//code to use if directory
}
}
I am trying this also but i got empty array
$path = 'D:\tests\Ed';
$folders=glob("{$path}/*");
print_r($folders);
the only way i could run the code is by putting the folder in the project directory ,
$path = 'C:\wamp\www\my project php\ED';
but is there another way?

rename file is not working on php

Hi i have problem with this code
with the code i can change whole my folder file to number like 1.mp4 2.mp4 ect...
i test the code and i print the name of the file from it and every thing is right
but rename function is not working
this is my code
$dir = opendir('.');
$i = 1;
// loop through all the files in the directory
while (false !== ($file = readdir($dir)))
{
// if the extension is '.mp4'
if (strtolower(pathinfo($file, PATHINFO_EXTENSION)) == 'mp4')
{
echo $file ;
// do the rename based on the current iteration
$newName = $i . '.mp4';
rename($file, $newName);
// increase for the next loop
$i++;
}
}
// close the directory handle
closedir($dir);
?>
what is the problem now ?
NEW iNFO
i tried the code inside my localhost and it's work but it's not working inside the server
It's more efficient to use glob()
foreach(glob(__DIR__ . '/*.mp4') as $key => $file) {
if(!rename($file, __DIR__ . '/' . ($key + 1) . '.mp4')) {
throw new Exception('Unable to write to '. $file);
}
}
I'll hazard a guess it's a write permissions issue though - I don't see anything directly wrong with the script.
Getting the real path can help:
$file = realpath($filename);
but it sounds like it could be a permissions issue or an SELinux issue also. You will need apache to be the group on the files in question, and the files should be writeable by the group.
Also, if you have SELinux enabled, you will need to use
semanage fcontext -a -t httpd_sys_rw_content_t "/path/to/images/folder(/.*)?"
and
restorecon -R -v /path/to/images/folder

PHP GAE readdir() doesn't work as intended

I'm trying to recursively list every file that is in my bucket. It's not too many files but I'd like to list them to test a few things. This code works on a normal file system but it's not working on Google Cloud Storage.
Anyone have any suggestions?
function recurse_look($src) {
$dir = opendir($src);
while(false !== ( $file = readdir($dir)) ) {
if (( $file != '.' ) && ( $file != '..' )) {
if ( is_dir($src . '/' . $file) ) {
recurse_look($src . '/' . $file);
}
else {
echo $src . '/' . $file;
echo "<br />";
}
}
}
closedir($dir);
}
recurse_look("gs://<BUCKET>");
Personally, I would recommend not using a filesystem-impersonation abstraction layer on top of Google Cloud Storage, for a task such as listing everything inside a bucket -- rather, just reach out for the underlying functionality.
In particular, see https://cloud.google.com/storage/docs/json_api/v1/json-api-php-samples for everything about authentication etc, and, once, that's taken care of, focus on just one line in the example:
$objects = $storageService->objects->listObjects(DEFAULT_BUCKET);
This is all you need to list all objects in a bucket (which is not the same thing as "files in a directory", and the "filesystem simulations" on top of buckets and objects, I offer as being just my personal opinion, end up hurting rather than helping despite their excellent intentions:-).
Now if the objects' names contain e.g slashes and you want to take that into account as symbolically signifying something or other, go right ahead, but at least this way you're sure you're getting all the objects actually existing in the bucket, and, nothing but those!-)
Now that glob is working, you can try something like this
function lstree($dir) {
foreach (glob($dir . '/*') as $path) {
if (is_dir($path)) {
echo $path;
lstree($path);
} else {
echo $path;
}
}
lstree('gs://{bucket}/');

List files and subfolders from database in PHP

Beginner : I cant seem to get my head around the logic of it. Have searched but seems to come up with listing files and folders from an actual directory ie. (opendir).
My problem is :
Im trying to work out (in PHP) how to list files and subfolders from a path stored in a database. (Without any access to the file or dir, so just from the path name)
For example database shows:
main/home/television.jpg
main/home/sofa.jpg
main/home/bedroom/bed.jpg
main/home/bedroom/lamp.jpg
So if i specify main/home - it shows: television.jpg, sofa.jpg and the name of the subfolder : bedroom.
scanFolder('main/home');
function scanFolder($dir) {
foreach (scandir($dir) as $file) {
if (!in_array($file, array('.', '..'))) {
if (is_dir($file)) {
scanFolder($dir . '/' . $file);
}
else {
echo $dir . '/' . $file . "\n";
}
}
}
}
You would probably want to check on each iteration if the filename is a directory or not. If it is, open it up and read its contents and output them. A recursive function would work best in this situation.
http://php.net/manual/en/function.is-dir.php

PHP / Windows - Opendir() fails opening subdirectories within symbolic linked directories

Does anyone know a solution to this problem? I'm unable to open a subdirectory within a symboliclink'd directory. I've confirmed that the paths are correct (even copy & pasted the path into explorer, which parsed it fine). This is a strange, annoying, bug :|.
Example:
C:\folder\symbolic_link\dir1\dir2 - opening dir2 fails.
C:\folder\symbolic_link\dir1 - works
C:\folder\real_directory\dir1\dir2 - works
C:\folder\real_directory\dir1 - works
Alright, I finally found a hack to solve this bug in php's handling of symlinks on windows. The bug occurs when recursively iterating through files/directories using opendir(). If a symlink to a directory exists in the current directory, opendir() will fail to read the directories in the directory symlink. It is caused by something funky in php's statcache, and can be resolved by calling clearstatcache() before calling opendir() on the directory symlink (also, the parent directory's file-handle must be closed).
Here is an example of the fix:
<?php
class Filesystem
{
public static function files($path, $stats = FALSE)
{
clearstatcache();
$ret = array();
$handle = opendir($path);
$files = array();
// Store files in directory, subdirectories can't be read until current handle is closed & statcache cleared.
while (FALSE !== ($file = readdir($handle)))
{
if ($file != '.' && $file != '..')
{
$files[] = $file;
}
}
// Handle _must_ be closed before statcache is cleared, cache from open handles won't be cleared!
closedir($handle);
foreach ($files as $file)
{
clearstatcache($path);
if (is_dir($path . '/' . $file))
{
$dir_files = self::files($path . '/' . $file);
foreach ($dir_files as $dir_file)
{
$ret[] = $file . '/' . $dir_file;
}
}
else if (is_file($path . '/' . $file))
{
$ret[] = $file;
}
}
return $ret;
}
}
var_dump(filessystem::files('c:\\some_path'));
Edit: It seems that clearstatcache($path) must be called before any file-handling functions on the symlink'd dir. Php isn't caching symlink'd dirs properly.

Categories