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. Filesystem (Sistema de arquivos)
Dependências
Nenhuma biblioteca externa é necessária para compilar esta extensão.
Instalação
Não há nenhuma instalação necessária para utilizar estas funções, elas fazem parte do núcleo do PHP.
Configurações em execução
O comportamento dessas funções podem ser modificado pelas configurações do php.ini.
Tabela 1. Opções de configuração do Filesystem e Streams
| Nome | Padrão | Alterável |
|---|---|---|
| allow_url_fopen | "1" | PHP_INI_ALL |
| user_agent | NULL | PHP_INI_ALL |
| default_socket_timeout | "60" | PHP_INI_ALL |
| from | NULL | ?? |
| auto_detect_line_endings | "Off" | PHP_INI_ALL |
Descrição resumida das diretivas de configuração.
- allow_url_fopen boolean
Esta opção ativa o dispositivo URL fopen wrappers que permite o acesso a objetos URL como arquivos. São disponibilizados por padrão wrappers para acesso de arquivos remotos utilizando os protocolos FTP ou HTTP, e algumas estensões como a zlib podem registar wrappers adicionais.
Nota: Esta opção foi introduzida imediatamente antes da liberação da versão 4.0.3. Até essa versão e incluindo a 4.0.3, você somente podia desabilitar este recurso na compilação, usando a opção --disable-url-fopen-wrapper.
Atenção Nas versões Windows anterioes a PHP 4.3, as funções seguintes não suportavam acesso de arquivos remotos: include(), include_once(), require(), require_once() e as funções imagecreatefromXXX da extensão Referência LXII, Imagens, Funções de.
- user_agent string
Define o user agent que o PHP irá enviar.
- default_socket_timeout integer
Timeout padrão (em segundos) para streams baseados em socket.
Nota: Esta opção de configuração foi incluida no PHP 4.3.
- from="joe@example.com" string
Define a senha do FTP anonimo (seu endereço de e-mail).
- auto_detect_line_endings boolean
Quando ativo, o PHP irá examinar os dados lidos por fgets() e file() para verificar se está sendo utilizado a convensão de fim de linha Unix, MS-DOS ou Macintosh.
Isto ativa a interoperabilidade do PHP com sistemas Macintosh, mas seu padrão é Off, porque isso causa uma pequena perda de performance na detecção da convenção de fim de linha num primeiro momento e porque as pessoas que utilizam o fim de linha como separadores de itens sob sistemas Unix podem experimentar problemas de falta de compatibilidade.
Nota: Esta opção de configuração foi introduzida no PHP 4.3.
Constantes pré-definidas
As contantes abaixo são definidas por esta extensão e somente estarão disponíveis quando a extensão foi compilada com o PHP ou carregada dinamicamente durante a execução.
- GLOB_BRACE (integer)
- GLOB_ONLYDIR (integer)
- GLOB_MARK (integer)
- GLOB_NOSORT (integer)
- GLOB_NOCHECK (integer)
- GLOB_NOESCAPE (integer)
- PATHINFO_DIRNAME (integer)
- PATHINFO_BASENAME (integer)
- PATHINFO_EXTENSION (integer)
- FILE_USE_INCLUDE_PATH (integer)
- FILE_APPEND (integer)
- FILE_IGNORE_NEW_LINES (integer)
- FILE_SKIP_EMPTY_LINES (integer)
Veja também
Para funções relacionadas, veja também as seções Deritório e Execução de Programas.
Para uma lista e descrição dos vários wrappers URL que podem ser utilizados como arquivos remotos, veja em Apêndice M.
- Índice
- basename -- Retorna a parte nome do arquivo do caminho/path
- chgrp -- Modifica o grupo do arquivo
- chmod -- Modifica as permissões do arquivo
- chown -- Modifica o dono do arquivo
- clearstatcache -- Limpa as informações em cache de arquivos
- copy -- Copia arquivo
- delete -- Veja unlink() ou unset()
- dirname -- Retorna o componente diretório de um caminho/path
- disk_free_space -- Retorna o espaço disponivel no diretório
- disk_total_space -- Retorna o tamanho total do diretório
- diskfreespace -- Sinônimo de disk_free_space()
- fclose -- Fecha um ponteiro de arquivo aberto
- feof -- Testa pelo fim-de-arquivo (eof) em um ponteiro de arquivo
- fflush -- Força a liberação do buffer para um arquivo
- fgetc -- Le um caracter do ponteiro de arquivo
- fgetcsv -- Le uma linha do ponteiro de arquivos e a interpreta por campos CSV
- fgets -- Le uma linha de um ponteiro de arquivo
- fgetss -- Ler uma linha de um ponteiro de arquivo e retira as tags HTML
- file_exists -- Checa se um arquivo ou diretório existe
- file_get_contents -- Le todo o conteúdo de um arquivo para uma string
- file_put_contents -- Escreve uma string para um arquivo
- file -- Le um arquivo inteiro para um array
- fileatime -- Obtém o último horário de acesso do arquivo
- filectime -- Ler o tempo de modificação do inode do arquivo
- filegroup -- Lê o grupo do arquivo
- fileinode -- Lê o inode do arquivo
- filemtime -- Le o tempo de modificação do arquivo
- fileowner -- Lê o dono (owner) do arquivo
- fileperms -- Lê as permissões do arquivo
- filesize -- Lê o tamanho do arquivo
- filetype -- Lê o tipo de arquivo (file type)
- flock -- Monitor de travamento de arquivos portátil
- fnmatch -- Verifica se um nome de arquivo bate com padrão (wildcards)
- fopen -- Abre um arquivo ou uma URL
- fpassthru -- Imprime todo os dados restantes de um ponteiro de arquivo
- fputcsv -- Formata a linha como um CSV e escreve em um ponteiro de arquivo
- fputs -- Sinônimo de fwrite()
- fread -- Leitura binary-safe de arquivo
- fscanf -- Interpreta a leitura de um arquivo de acordo com um formato
- fseek -- Procura (seeks) em um ponteiro de arquivo
- fstat -- Lê a informação sobre um arquivo usando um ponteiro de arquivo aberto
- ftell -- Retorna a posição de leitura/gravação do ponteiro do arquivo
- ftruncate -- Corta (trunca) um arquivo para um tamanho especificado
- fwrite -- Gravação em arquivos binary-safe
- glob -- Localiza diretórios/arquivos que combinem com o padrão
- is_dir -- Diz se o caminho é um diretório
- is_executable -- Diz se um arquivo é executável
- is_file -- Diz se o arquivo é um arquivo comum (não é diretório)
- is_link -- Diz se o arquivo é um link simbólico (symbolic link)
- is_readable -- Diz se o arquivo é legivel (readable)
- is_uploaded_file -- Diz se o arquivo foi uploaded via HTTP POST
- is_writable -- Diz se pode-se escrever para o arquivo (writable)
- is_writeable -- Esta é uma função sinônima (alias) de is_writable()
- lchgrp -- Changes group ownership of symlink
- lchown -- Changes user ownership of symlink
- link -- Criando um hard link
- linkinfo -- Ler informações sobre um link
- lstat -- Obtem informações sobre um arquivo ou link simbólico
- mkdir -- Criar um diretório
- move_uploaded_file -- Move um arquivo carregado para uma nova localização
- parse_ini_file -- Interpreta um arquivo de configuração
- pathinfo -- Retorna informação sobre o path de um arquivo
- pclose -- Fecha um processo de um ponteiro de arquivo
- popen -- Abre um processo como ponteiro de arquivo
- readfile -- Lê e exibe o conteúdo de um arquivo
- readlink -- Retornar o alvo de um link simbólico
- realpath -- Retorna o path absoluto canonicalizado
- rename -- Renomear um arquivo
- rewind -- Reinicializa a posição do ponteiro de arquivos para o início
- rmdir -- Remove um diretório
- set_file_buffer -- Sinônimo de stream_set_write_buffer()
- stat -- Obtem informações sobre um arquivo
- symlink -- Cria um link simbólico
- tempnam -- Cria um nome de arquivo único
- tmpfile -- Cria um arquivo temporário
- touch -- Muda o tempo de modificação do arquivo
- umask -- Modificar a umask atual
- unlink -- Apaga um arquivo
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);
}
