Calculer la taille d'un dossier

ViPHP
fab
ViPHP | 2657 Messages

12 nov. 2005, 02:27

j'avais du temps a perdre alors j'ai fais une fonction qui compte la taille d'un dossier en additionant la taille de tous les fichiers, résursif bien sur
<?php
/* 
Liscence : GPL
Author : fab
Mail : [email protected]
*/

/**
@function calc_size 
@param text dir rép dont on veut connaitre la taille

@return numeric

formate la taille retourné par la fonction calc_size_Rdir
*/
function calc_size($dir)
{
	$size = calc_size_Rdir($dir);
	$filesizename = array(" Bytes", " KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB");
	return round($size/pow(1024, ($i = floor(log($size, 1024)))), 2) . $filesizename[$i];
}
/**
@function calc_size_Rdir
@param text dir_start dossier dont on va calculer la taille

@return numeric

calcul de la taille d'un dossier en ajouter celle de ses fichiers
*/

function calc_size_Rdir($dir_start)
{
	$size = 0;
	$open = opendir($dir_start);
	while($file = readdir($open))
	{
		if($file != '.' && $file != '..')
		{
			if(is_dir($dir_start .'/'.$file))
			{
				$new_dir = $dir_start .'/'.$file;
				$size = $size + calc_size_Rdir($new_dir);
			}
			else
			{
				$size = $size + filesize($dir_start .'/'.$file);
			}
		}
	}
	return $size;
}
?>
example d'utilisation :
<?php
$dir = getcwd();
$size = calc_size($dir);
echo $size;
?>
dans mon cas ça retourne 14 MB :)
Seul l'intelligent a le pouvoir de se trouver con
try { work(); } catch(FlemmeExeption $e) { sleep(84600); }

ViPHP
fab
ViPHP | 2657 Messages

12 nov. 2005, 02:36

voici une autre fonction du même style sauf que celle là compte le nombres de fichiers
<?php
/* 
Liscence : GPL
Author : fab
Mail : [email protected]
*/

/**
@function count_files_Rdir
@param text dir_start dossier dont on va calculer le nombre de fichiers

@return numeric

calcul du nombres de fichiers dans un dossier, fonction récursive
*/

function count_files_Rdir($dir_start)
{
	$number = 0;
	$open = opendir($dir_start);
	while($file = readdir($open))
	{
		if($file != '.' && $file != '..')
		{
			if(is_dir($dir_start .'/'.$file))
			{
				$new_dir = $dir_start .'/'.$file;
				$number = $number + count_files_Rdir($new_dir);
			}
			else
			{
				$number++;
			}
		}
	}
	return $number;
}
?>
exemple d'utilisation :
<?php
$dir = getcwd();
$number = count_files_Rdir($dir);
echo $number;
?>
Modifié en dernier par fab le 30 nov. 2005, 22:20, modifié 1 fois.
Seul l'intelligent a le pouvoir de se trouver con
try { work(); } catch(FlemmeExeption $e) { sleep(84600); }

Mammouth du PHP | 1885 Messages

12 nov. 2005, 08:07

Bien qu'il ne s'agisse pas directement de PHP, il existe une commande dans l'environnement Unix qui permet de calculer la taille du contenu d'un répertoire:

Code : Tout sélectionner

du -chs DIRECTORY
Ainsi le script suivant retournerait la taille du dossier passé en paramètre. Il faut cependant noter que vous devez avoir accès à la fonction shell_exec(), ce qui relativement rare chez les hébergeurs mutualisés grand public.
<?php
function du($directory) {

	// Contrôle de l'existance du répertoire
	if (FALSE === file_exists($directory) {
		return FALSE;
	}

	// Retour du résultat de la commande
	return $size = shell_exec('du -chs ' . escapeshellarg($directory) . ' | tail -1 | cut -f1');
}
?>
Seul l'existence du répertoire est testé et le résultat de la commande n'est pas vérifié. Les commandes tail et cut sont utilisés afin d'isoler le résultat et retourner une taille au format "humain".

Exemple d'exécution réel:
<?php
// Affiche "1.4M"
print du('./webmail/');
?>
La programmation est l'expression de la poésie d'un programmeur
Génération PHP

ViPHP
fab
ViPHP | 2657 Messages

12 nov. 2005, 13:47

ouep je connais mais mon poste de travail est sous windows :)
Seul l'intelligent a le pouvoir de se trouver con
try { work(); } catch(FlemmeExeption $e) { sleep(84600); }

Mammouth du PHP | 1885 Messages

12 nov. 2005, 22:37

Bien qu'il ne s'agisse pas directement de PHP, il existe une commande dans l'environnement Unix qui permet de calculer la taille du contenu d'un répertoire...
:)
La programmation est l'expression de la poésie d'un programmeur
Génération PHP

Petit nouveau ! | 3 Messages

22 mars 2006, 00:07

Fab, merci pour ce scrip. J'ai mis du tps a comprendre comment faire pour lui signaler le dossier :oops:

Si il y a des boulets comme moi, il faut remplacer

Code : Tout sélectionner

$dir = getcwd();
par
$dir = 'ledossier';
Bref, voila mon probleme.
J'ai des utilisateurs qui peuvent uper des fichiers sur un serveur.
Chaque utilisateur a un repertoire.
Maintenant je souhaite y ajouter un "quotas"
par exemple :

Code : Tout sélectionner

si dirX >= 20 Mo autorisé le UP sinon interdire
voir meme

Code : Tout sélectionner

si dirX >= 20 Mo affiché le formulaire de UP sinon le caché ou affiché autre chose
Est ce que cela est possible ???
Quelles pistes dois je explorées ???
Merci

ViPHP
fab
ViPHP | 2657 Messages

22 mars 2006, 01:29

tu dois juste utiliser la fonction calc_size_Rdir directement mais attention celle-ci te retourne une valeur en octets donc ton 20go = 20*1024
Seul l'intelligent a le pouvoir de se trouver con
try { work(); } catch(FlemmeExeption $e) { sleep(84600); }

Petit nouveau ! | 3 Messages

22 mars 2006, 01:41

tu dois juste utiliser la fonction calc_size_Rdir directement mais attention celle-ci te retourne une valeur en octets donc ton 20go = 20*1024
Comment ca ???

Je dois juste utilisé ceci :
function calc_size_Rdir($dir_start) 
{ 
    $size = 0; 
    $open = opendir($dir_start); 
    while($file = readdir($open)) 
    { 
        if($file != '.' && $file != '..') 
        { 
            if(is_dir($dir_start .'/'.$file)) 
            { 
                $new_dir = $dir_start .'/'.$file; 
                $size = $size + calc_size_Rdir($new_dir); 
            } 
            else 
            { 
                $size = $size + filesize($dir_start .'/'.$file); 
            } 
        } 
    } 
    return $size; 
} 
Et apres utilisé un truc du genre
// 20Mo*1024
if ($size >= 20480)
{
//impossible de DL
}
else
{
//possibilité de DL
}
Et je colle la foction en debut de fichier c'est bien cela.
Désolé je debut et je rame.
En tout cas merci du soutient

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

22 mars 2006, 05:14

Notez que pour le parcours de dossier il existe la fonction hélas trop méconnue glob, qui simplifie grandement ce type de processus :
function calc_size_Rdir($dir_start) 
{ 
    $size = 0; 
    $files = glob("$dir_start/*");
    if ($files) foreach ($files as $file) {
        if (is_dir($file))
            $size += calc_size_Rdir($file);
        else
            $size += filesize($file);
    }
    return $size;
}

function count_files_Rdir($dir_start) 
{ 
    $number = 0; 
    $files = glob("$dir_start/*");
    if ($files) foreach ($files as $file) {
        if (is_dir($file))
            $number += count_files_Rdir($file);
        else
            $number ++;
    }
    return $number;
}
Modifié en dernier par naholyr le 22 mars 2006, 13:22, modifié 1 fois.

Petit nouveau ! | 3 Messages

22 mars 2006, 13:20

bonjour, je me permet de repassé car je n'ai toujours pas reglé mon probleme.

Voila j'ai un repertoire upload dans lequel se trouve des repertoire crée lors de l'envoie de fichier par les utilisateurs.
  • 1
  • 3
  • 4
  • etx...
Les numero son atribué en fonction de l'ID sur la BdD.
Je souhaiterais que si le repertoire 1 est > a 10 ou 20 Mo, l'uploadsoit impossible.

Pour cela, j'ai crée un fichier controle.php que j'ai mis dans le repertoir upload.
controle.php
<?

function calc_size_Rdir($dir_start)
{ 
    $taille = 0;
    $fichiers = glob("$dir_start/*");
    foreach ($fichiers as $fichier) {
        if (is_dir($fichier))
            $taille += calc_size_Rdir($fichier);
        else
            $taille += filesize($fichier);
    }
    return $taille;
}
 $dir_start = 1;
 $taille = calc_size_Rdir($dir_start);
  echo $taille ;


?>
Celui ci me renvoie : 26202
Ce qui est bon. Ce sont des octets.
Mais quand je tente de placer mon controle.php a l'endroit ou s'effectue l'upload, on me renvoie l'erreur
Invalid argument supplied for foreach()
Je comprend pas trop.
P.S j'espere que je poste au bon endroit.

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

22 mars 2006, 13:24

Tu as utilisé ma version avec glob qui contenait une erreur : si aucun fichier ne correspond au masque, glob(masque) renvoie false au lieu de renvoyer array() (un peu stupide question cohérence du type de retour, mais ça n'est ni la première ni la dernière incohérence de ce type en PHP).
Il faut donc vérifier le retour avec "if ($files)" avant le foreach, j'ai édité mon premier message.

Mammouth du PHP | 1311 Messages

22 mars 2006, 21:51

salut
ma petite contribution pour php5.1.2
compte le nombre de fichier mais pas le poids(encore)
soyez indulgent je n'ai quasiment pas testé
class FileSysteme extends SingletonFactory implements IteratorAggregate
{
	private $result = array();

	private $filter = 'all';

	private $countfile = 0;
	private $countDir = 0;

	public static $Type = 'file';

	public function __construct(){
		
	}

	public static final function Singleton($instance_id = null){
		return parent::Singleton(__CLASS__);
	}

	public function __set($name,$value){
		switch ($name){
			case 'filter':$this->filter = $value;break;
			default:break;
		}
	}

	public function listDirectory( $dirname , $recursif = false){
		$dir = new RecursiveDirectoryIterator( $dirname );
		if( $recursif ){
			self::getFilesRecursif($dir);
		}
		else{
			self::getFiles($dir);
		}
	}


	private function getFiles( $rdi ){
		if($rdi instanceof RecursiveDirectoryIterator )
		{
			for ($rdi->rewind();$rdi->valid();$rdi->next()){
				if(!$rdi->isDot()){
					if(FileSysteme::$Type === 'file' && $rdi->isFile){
						$this->getFile($rdi);
					}elseif (FileSysteme::$Type === 'Directory' && $rdi->isDir){
						$this->getDir($rdi);
					}
				}
			}
		}
	}


	private function getFilesRecursif($rdi,$depth=0) {
		if($rdi instanceof RecursiveDirectoryIterator )
		{
			for ($rdi->rewind();$rdi->valid();$rdi->next()) {
				if ($rdi->isDot()){
					continue;
				}
				if ($rdi->isDir() || $rdi->isFile() ) {
					if(FileSysteme::$Type === 'file' && $rdi->isFile){
						$this->getFile($rdi);
					}elseif (FileSysteme::$Type === 'Directory' && $rdi->isDir()){
						$this->getDir($rdi);
					}
					if ($rdi->hasChildren()){
						self::getFilesRecursif($rdi->getChildren(),1+$depth);
					}
				}
			}
		}
	}

	
	private function getFile($rdi){
		if($rdi->isFile() && is_array($this->filter) && in_array($this->getExtention($rdi->current()),$this->filter)){
			$this->countfile++;
			$this->result[] = $rdi->current();
		}
		elseif ($rdi->isFile() && $this->filter == 'all'){
			$this->countfile++;
			$this->result[] = $rdi->current();
		}
	}
	
	private function getDir($rdi){
		if($rdi->isDir()){
			$this->countDir++;
			$this->result[] = $rdi->current();
		}
	}
	
	
	public function getfileNumber(){
		return $this->countfile;
	}

	public function getDirNumber(){
		return (int)$this->countDir;
	}
	
	private function getExtention( $filename ){
		if(is_file($filename)){
			$tableau = explode('.',$filename);
			return (string) array_pop($tableau);
		}
		else {
			return true;
		}
	}

	public function getIterator(){
		$iterator = new Iterators($this->result);
		return $iterator;
	}
}
?>
et l'utilisation
<?php

function __autoload($class){
	if($class !==""){
	require_once $class.'.class.php';
	}
}
//set_time_limit(360);
$dir = FileSysteme::Singleton();
FileSysteme::$Type = 'Directory';
$dir->filter = array('php');


$dir->listDirectory('e:wamp',true);

foreach ($dir as $val){
	echo $val.'<br/>';
}

echo $dir->getFileNumber();
?>

Mammouth du PHP | 983 Messages

23 mars 2006, 01:00

Je vois pas à quoi sert le singleton là ?

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

23 mars 2006, 01:51

C'est un peu le marteau-piqueur pour tuer un moustique là :?

Mammouth du PHP | 983 Messages

23 mars 2006, 10:18

Issu de scriptsphp.org
<?php
class treeDirectory {
    
    private $iterator = false;

    public function __construct($directory) {
        $this->iterator = new recursiveDirectoryIterator($directory);
    }

    public function displayTree($iterator = false) {
        if(!$iterator) {
            $iterator = $this->iterator;
        }
        echo '<ul>';
        while($iterator->valid()) {
            if($iterator->isDir() AND !$iterator->isDot()) {
                echo '<li><strong style="color: red;">' , $iterator->current() , '</strong></li>';
                if($iterator->hasChildren()) {
                    echo '<ul>' , $this->displayTree($iterator->getChildren()) , '</ul>';
                }
            } else {
                if($iterator->isFile()) {
                    echo '<li>' , $iterator->getFilename() , '</li>';
                }
            }
            $iterator->next();
        }
        echo '</ul>';
    }
}

try {
    $D = new treeDirectory('.');
    $D-> displayTree();
} catch(Exception $e) {
    echo '<pre>' , $e , '</pre>';
}
?>
Il suffit d'adapter pour ajouter un compteur et virer les echo ;)