You have an array of directories (straightforward list of directories):
<?php
$array = array(
'/home/drapeko/var',
'/home/drapeko/var/y',
'/home/drapeko',
'/home',
'/var/libexec'
);
);
?>
And you would like to transform this array to hierarchy of directories:
<?php
$array = array (
'home' => array (
'drapeko' => array (
'var' => array (
'y' => array()
)
)
),
'var' => array(
'libexec' => array()
)
);
?>
How can you do it?
First of all the below function will help us.
<?php
/**
* This function converts real filesystem path to the string array representation.
*
* for example,
* '/home/drapeko/var/y will be converted to $result_array['home']['drapeko']['var']['y']
* '/home/drapeko/var/y/file.txt will be converted to $result_array['home']['drapeko']['var']['y']
*
* @param $path realpath of the directory
* @return string string array representation of the path
*/
function pathToArrayStr($path) {
// TODO constants/configs?
$res_path = str_replace(array(':/', ':\\', '/', '\\', DIRECTORY_SEPARATOR), '/', $path);
// if the first or last symbol is '/' delete it (e.g. for linux)
$res_path = preg_replace(array("/^\//", "/\/$/"), '', $res_path);
// create string
$res_path = '[\''.str_replace('/', '\'][\'', $res_path).'\']';
return $res_path;
}
?>
It simply converts the real path of the file to array string representation.
How can you use this function? I know it looks like a little confusing. But it's quite simple. Consider the example below:
<?php
$result = array();
$check = array();
foreach($array as $val) {
$str = pathToArrayStr($val, 'result');
foreach($check as $ck) {
if (strpos($ck, $str) !== false) {
continue 2;
}
}
$check[] = $str;
eval('$result'.$str.' = array();');
}
print_r($result);
?>
Heh, how do you find it? This approach has helped me very much. I hope you will find it useful. :)
XL. Système de fichiers
Pré-requis
Aucune bibliothèque externe n'est requise pour avoir cette extension, mais si vous voulez le support des grands fichiers LFS sur Linux, vous devez avoir une version récente de gclib et vous devrez compiler PHP avec les options suivantes : -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64.
Installation
Il n'y pas d'installation nécessaire pour utiliser ces fonctions, elles font parties du coeur de PHP.
Configuration à l'exécution
Le comportement de ces fonctions est affecté par la configuration dans le fichier php.ini.
Tableau 1. Options de configuration
| Nom | Par défaut | Modifiable | Historique |
|---|---|---|---|
| allow_url_fopen | "1" | PHP_INI_SYSTEM | PHP_INI_ALL dans PHP <= 4.3.4. Disponible depuis PHP 4.0.4. |
| user_agent | NULL | PHP_INI_ALL | Disponible depuis PHP 4.3.0. |
| default_socket_timeout | "60" | PHP_INI_ALL | Disponible depuis PHP 4.3.0. |
| from | "" | PHP_INI_ALL | |
| auto_detect_line_endings | "0" | PHP_INI_ALL | Disponible depuis PHP 4.3.0. |
Voici un éclaircissement sur l'utilisation des directives de configuration.
- allow_url_fopen booléen
Cette option active les versions étendues des fonctions d'accès aux fichiers, qui savent exploiter les URL. Les extensions par défaut permettent d'accéder aux fichiers distants avec les protocoles FTP ou HTTP. Certaines extensions comme zlib, peuvent ajouter d'autres fonctionnalités.
Note : Cette option peut seulement être définie dans le php.ini pour des raisons de sécurité.
Note : Cette option a été introduite immédiatement après la publication de la version 4.0.3. Pour les versions jusqu'à la, vous ne pouvez désactiver cette fonctionnalité qu'au moment de la compilation, avec l'option --disable-url-fopen-wrapper.
Avertissement Sous Windows, dans les versions antérieures à la version 4.3, les fonctions suivantes ne supportent pas l'accès aux fichiers distants : include(), include_once(), require(), require_once() et les fonctions imagecreatefromXXX de l'extension Référence LXII, Images.
- user_agent string
Définit le type d'"user agent" (Définition du navigateur web) utilisé par PHP.
- default_socket_timeout entier
Durée d'expiration (en secondes) pour les flots basés sur les sockets.
Note : Cette option de configuration a été introduite en PHP 4.3.
- from string
Définit le mot de passe FTP en mode anonyme (en général, votre adresse email).
- auto_detect_line_endings booléen
Lorsque cette option est activée, PHP va examiner les données lues par fgets() et file() pour voir si le fichier utilise les conventions de ligne de Unix, MS-Dos ou Macintosh.
Cela permet à PHP de fonctionner avec des systèmes Macintosh, mais par défaut, cette option est désactivée, car cette détection impose un légère pénalité en temps de traitement, mais aussi parce que ceux qui utilisent les retours chariots comme séparateurs auront des soucis de compatibilité.
Note : Cette option de configuration a été introduite en PHP 4.3.
Constantes pré-définies
Ces constantes sont définies par cette extension, et ne sont disponibles que si cette extension a été compilée avec PHP, ou bien chargée au moment de l'exécution.
- GLOB_BRACE (entier)
- GLOB_ONLYDIR (entier)
- GLOB_MARK (entier)
- GLOB_NOSORT (entier)
- GLOB_NOCHECK (entier)
- GLOB_NOESCAPE (entier)
- PATHINFO_DIRNAME (entier)
- PATHINFO_BASENAME (entier)
- PATHINFO_EXTENSION (entier)
- PATHINFO_FILENAME (entier)
Since PHP 5.2.0.
- FILE_USE_INCLUDE_PATH (entier)
- FILE_APPEND (entier)
- FILE_IGNORE_NEW_LINES (entier)
- FILE_SKIP_EMPTY_LINES (entier)
Voir aussi
Pour les fonctions connexes, voyez aussi la section sur les accès aux Dossiers et sur les exécutions de programme.
Pour une liste et une explication sur les différents outils d'accès aux fichiers distants, voyez aussi Annexe M.
- Table des matières
- basename -- Sépare le nom du fichier et le nom du dossier
- chgrp -- Change le groupe propriétaire d'un fichier
- chmod -- Change le mode du fichier
- chown -- Change le groupe propriétaire du fichier
- clearstatcache -- Efface le cache de stat()
- copy -- Copie un fichier
- delete -- Effacer
- dirname -- Renvoie le nom du dossier
- disk_free_space -- Renvoie l'espace disque disponible dans le répertoire
- disk_total_space -- Retourne la taille d'un dossier
- diskfreespace -- Alias de disk_free_space()
- fclose -- Ferme un fichier
- feof -- Teste la fin du fichier
- fflush -- Envoie tout le contenu généré dans un fichier
- fgetc -- Lit un caractère dans un fichier
- fgetcsv -- Renvoie la ligne courante et cherche les champs CSV
- fgets -- Renvoie la ligne courante sur laquelle se trouve le pointeur du fichier
- fgetss -- Renvoie la ligne courante du fichier et élimine les balises HTML
- file_exists -- Vérifie si un fichier existe
- file_get_contents -- Lit tout un fichier dans une chaîne
- file_put_contents -- Ecrit une chaîne dans un fichier
- file -- Lit le fichier et renvoie le résultat dans un tableau
- fileatime -- Renvoie la date à laquelle le fichier a été accédé pour la dernière fois
- filectime -- Renvoie la date de dernier accès à un inode
- filegroup -- Lire le nom du groupe
- fileinode -- Renvoie le numéro d'inode du fichier
- filemtime -- Renvoie la date de dernière modification du fichier
- fileowner -- Renvoie le nom du propriétaire du fichier
- fileperms -- Renvoie les permissions affectées à un fichier
- filesize -- Renvoie la taille d'un fichier
- filetype -- Retourne le type de fichier
- flock -- Verrouille le fichier
- fnmatch -- Repère un fichier à partir d'un masque
- fopen -- Ouverture d'un fichier ou d'une URL
- fpassthru -- Affiche le reste du fichier
- fputcsv -- Formate une ligne en CSV et l'écrit dans un fichier
- fputs -- Alias de fwrite()
- fread -- Lecture du fichier en mode binaire
- fscanf -- Analyse un fichier en fonction d'un format
- fseek -- Modifie la position du pointeur de fichier
- fstat -- Lit les informations sur un fichier à partir d'un pointeur de fichier
- ftell -- Renvoie la position du pointeur du fichier
- ftruncate -- Tronque un fichier
- fwrite -- Ecrit un fichier en mode binaire
- glob -- Recherche des chemins qui vérifient un masque
- is_dir -- Indique si le fichier est un dossier
- is_executable -- Indique si le fichier est exécutable
- is_file -- Indique si le fichier est un véritable fichier
- is_link -- Indique si le fichier est un lien symbolique
- is_readable -- Indique si un fichier est autorisé en lecture
- is_uploaded_file -- Indique si le fichier a été téléchargé par HTTP POST
- is_writable -- Indique si un fichier est autorisé en écriture
- is_writeable -- Alias de is_writable()
- lchgrp -- Change l'appartenance du groupe d'un lien symbolique
- lchown -- Change l'appartenance du propriétaire d'un lien symbolique
- link -- Crée un lien
- linkinfo -- Renvoie les informations d'un lien
- lstat -- Retourne les informations sur n fichier ou un lien symbolique
- mkdir -- Crée un dossier
- move_uploaded_file -- Déplace un fichier téléchargé
- parse_ini_file -- Traite un fichier de configuration
- pathinfo -- Retourne des informations sur un chemin système
- pclose -- Ferme un processus de pointeur de fichier
- popen -- Crée un processus de pointeur de fichier
- readfile -- Affiche un fichier
- readlink -- Renvoie le nom du fichier vers lequel pointe un lien symbolique
- realpath -- Retourne le chemin canonique absolu
- rename -- Renomme un fichier ou un dossier
- rewind -- Replace le pointeur de fichier au début
- rmdir -- Efface un dossier
- set_file_buffer -- Alias de stream_set_write_buffer()
- stat -- Renvoie les informations à propos d'un fichier
- symlink -- Crée un lien symbolique
- tempnam -- Crée un fichier avec un nom unique
- tmpfile -- Crée un fichier temporaire
- touch -- Modifie la date de modification et de dernier accès d'un fichier
- umask -- Change le "umask" courant
- unlink -- Efface un fichier
I just learned that, to specify file names in a portable manner, you DON'T need 'DIRECTORY_SEPARATOR' - just use '/'. This really surprised and shocked me, as until now I typed about a zillion times 'DIRECTORY_SEPARATOR' to stay platform independent - unnecessary. Don't make the same mistake.
I made this function to search and/or display files by extension or for a string occurance in the filename. Any comments or enhancements are welcome offcourse. I'll update this function soon.
usage: list_files([string], [string], [int 1 | 0], [int 1 | 0]);
search for extension: list_files([string], [string], [0], [int 1 | 0]);
returns array: $myArray = list_files([string], [string], [0], [0]);
echo result: list_files([string], [string], [0], [1]);
search for string occurance: list_files([string], [string], [1], [int 1 | 0]);
returns array: $myArray = list_files([string], [string], [1], [0]);
echo result: list_files([string], [string], [1], [1]);
<?php
function list_files($directory, $stringSearch, $searchHandler, $outputHandler) {
$errorHandler = false;
$result = array();
if (! $directoryHandler = @opendir ($directory)) {
echo ("<pre>\nerror: directory \"$directory\" doesn't exist!\n</pre>\n");
return $errorHandler = true;
}
if ($searchHandler === 0) {
while (false !== ($fileName = @readdir ($directoryHandler))) {
if(@substr ($fileName, - @strlen ($stringSearch)) === $stringSearch) {
@array_push ($result, $fileName);
}
}
}
if ($searchHandler === 1) {
while(false !== ($fileName = @readdir ($directoryHandler))) {
if(@substr_count ($fileName, $stringSearch) > 0) {
@array_push ($result, $fileName);
}
}
}
if (($errorHandler === true) && (@count ($result) === 0)) {
echo ("<pre>\nerror: no filetype \"$fileExtension\" found!\n</pre>\n");
}
else {
sort ($result);
if ($outputHandler === 0) {
return $result;
}
if ($outputHandler === 1) {
echo ("<pre>\n");
print_r ($result);
echo ("</pre>\n");
}
}
}
?>
Here is a function I wrote to get the relative path between 2 files or directory.
We suppose that paths are wrotten in Unix format (/ instead of windows \\)
<?php
/**
* Return the relative path between two paths / Retourne le chemin relatif entre 2 chemins
*
* If $path2 is empty, get the current directory (getcwd).
* @return string
*/
function relativePath($path1, $path2='')
{
if ($path2 == '') {
$path2 = $path1;
$path1 = getcwd();
}
//Remove starting, ending, and double / in paths
$path1 = trim($path1,'/');
$path2 = trim($path2,'/');
while (substr_count($path1, '//')) $path1 = str_replace('//', '/', $path1);
while (substr_count($path2, '//')) $path2 = str_replace('//', '/', $path2);
//create arrays
$arr1 = explode('/', $path1);
if ($arr1 == array('')) $arr1 = array();
$arr2 = explode('/', $path2);
if ($arr2 == array('')) $arr2 = array();
$size1 = count($arr1);
$size2 = count($arr2);
//now the hard part :-p
$path='';
for($i=0; $i<min($size1,$size2); $i++)
{
if ($arr1[$i] == $arr2[$i]) continue;
else $path = '../'.$path.$arr2[$i].'/';
}
if ($size1 > $size2)
for ($i = $size2; $i < $size1; $i++)
$path = '../'.$path;
else if ($size2 > $size1)
for ($i = $size1; $i < $size2; $i++)
$path .= $arr2[$i].'/';
return $path;
}
?>
Enjoy ! :-)
This function searches a directory and returns an array of all files whose filename matches the specified regular expression. It's similar in concept to the Unix find program.
function findfile($location='',$fileregex='') {
if (!$location or !is_dir($location) or !$fileregex) {
return false;
}
$matchedfiles = array();
$all = opendir($location);
while ($file = readdir($all)) {
if (is_dir($location.'/'.$file) and $file <> ".." and $file <> ".") {
$subdir_matches = findfile($location.'/'.$file,$fileregex);
$matchedfiles = array_merge($matchedfiles,$subdir_matches);
unset($file);
}
elseif (!is_dir($location.'/'.$file)) {
if (preg_match($fileregex,$file)) {
array_push($matchedfiles,$location.'/'.$file);
}
}
}
closedir($all);
unset($all);
return $matchedfiles;
}
$htmlfiles = findfile('/some/dir','/\.(htm|html)$/');
I needed a function to find disk usage for a directory and its subs, so here it is. It's kinda like the Unix du program, except it returns the usage in bytes, not blocks.
function du($location) {
if (!$location or !is_dir($location)) {
return 0;
}
$total = 0;
$all = opendir($location);
while ($file = readdir($all)) {
if (is_dir($location.'/'.$file) and $file <> ".." and $file <> ".") {
$total += du($location.'/'.$file);
unset($file);
}
elseif (!is_dir($location.'/'.$file)) {
$stats = stat($location.'/'.$file);
$total += $stats['size'];
unset($file);
}
}
closedir($all);
unset($all);
return $total;
}
print du('/some/directory');
In the code samples of the user-contributed notes, you'll find functions that sometimes need a slash at the end of a folder path and sometimes don't.
Here's a little function to append a slash at the end of a path if there isn't one already.
function append_slash_if_none($string)
{
if (ereg ("/$", $string))
{
return $string;
}
else
{
return ereg_replace("$", "/", $string);
}
}
(Replace with a backslash if you're on Windows...)
Pollard@php.net contributed this in response to a question on setting these variables ...
This option *IS* settable within your PHP scripts.
Example:
<?php
ini_set('auto_detect_line_endings', true);
$contents = file('unknowntype.txt');
ini_set('auto_detect_line_endings', false);
$content2 = file('unixfile.txt');
?>
Note, with PHP 4.3 anytime Mac files are read using fgets or file you'll need to auto_detect_line_endings since \n is otherwise assumed. However, with PHP 5.0, stream_get_line() will allow you to specify what line ending character to read up to.
\\ Read a line from a MAC file
stream_get_line($fp, 4096, "\r");
\\ Read a line from a UNIX file
stream_get_line($fp, 4096, "\n");
\\ Read a line from a DOS file
stream_get_line($fp, 4096, "\r\n");
\\ Read a line up to any filesystem line ending
ini_set('auto_detect_line_endings', true); fgets($fp);
\\ You can also make up your own line ending characters:
\\ Read up to the first instance of ":"
stream_get_line($fp, 4096, ":");
Here is a useful function if you're having trouble writing raw bytes into a file.
It receives an integer and returns an array containing the ASCII values of the bytes on each index of the array.
function int2bytes($number){
$byte = $number;
$i=0;
do{
$dec_tmp = $byte;
$byte = bcdiv($byte,256,0);
$resto = $dec_tmp - (256 * $byte);
$return[] = $resto;
} while($byte >= 256);
if($byte) $return[] = $byte;
return array_reverse($return);
}
Example:
$arr = int2bytes(75832);
$arr will contain the following values:
Array
(
[0] => 1
[1] => 40
[2] => 56
)
Now, to write this data to the file, just use a fputs() with chr(), just like this:
fputs($fp,chr($arr[0]).chr($arr[1]).chr($arr[2]))
-- Regis
This is a function I use to determine if a file contains Binary information. I use this for my search engine so that it doesn't try to index files like .zip or .mp3 or any other file that doesn't contain readable information. It makes use of the Character Type Extension if it's loaded, if it's not then it uses Regular Expressions.
function is_binary($link)
{
$tmpStr = '';
@$fp = fopen($link, 'rb');
@$tmpStr = fread($fp, 256);
@fclose($fp);
if($tmpStr != '')
{
$tmpStr = str_replace(chr(10), '', $tmpStr);
$tmpStr = str_replace(chr(13), '', $tmpStr);
$tmpInt = 0;
for($i =0; $i < strlen($tmpStr); $i++)
{
if( extension_loaded('ctype') )
{
if( !ctype_print($tmpStr[$i]) )
$tmpInt++;
}
else
{
if( !eregi("[[:print:]]+", $tmpStr[$i]) )
$tmpInt++;
}
}
if($tmpInt > 5)
return(0);
else
return(1);
}
else
return(0);
}
