Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

Файловые функции (Юрий Насретдинов)
Goto page 1, 2  Next
Author Message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Tue Mar 18, 2003 10:48 pm (написано за 23 минуты 11 секунд)
   Post subject: Файловые функции
Reply with quote

В этой теме уже достаточно долгое время я выкладываю свои функции для работы с файлами, которых нет в стандартной поставке PHP, и многие из которых написаны с применением рекурсии, которая немного сложна для понимания новичками.

Функции, которые здесь представлены:

1) show_size($f,$format=true,$size=false) - показывает размер папки или файла $f, если $format=true или не указан, то вместо размера в байтах, возвращается строка, содержащая уже отформатированный размер - например не «10253», а «10.01 Kb». Как показывает практика, это более удобно, так как всё равно обычно приходится приводить всё к такому виду. Если указан третий параметр ($size), то функция просто оформляет указанный размер в виде "XX Kb" или "XX Mb", и т.д.

2) display_perms($f) - показывает права файла или папки $f в виде «drwxrwxrwx». ИМХО это наиболее естественное и удобное представление прав файлов и папок.

3) get_owner($file), get_group($file) - показывают соответственно владельца или группу *nix файла или папки $file. В Windows возвращается пустая строка.

4) remove_u($dir) - удаляет файл или папку $dir (папка может и не быть пустой). Постфикс «_u» у функций обозначает «universal» - универсальный, не зависящий от того, папка это или файл, работающий всегда.

5) chmoddir($dir,$mod) - выставляет права $mod папке $dir всем вложенным папкам и файлам

6) copy_u($src,$dest) - копирует папку или файл $src в указанное место $dest. Заметьте, что, естественно, в качестве $dest нужно указывать не папку, в которую нужно скопировать $src, а папку, которая должна в результате этого получиться. То же самое касается и файлов.

7) writefile(), file2string() и dirstats() - читайте описание функций, они не так часто используются, но описание на русском языке.


Извиняюсь за то, что некоторые комментарии на английском языке, что функции, вообще говоря, написаны в разном стиле и т.д... Они все писались в разное время и даже разными людьми, все проверены и отлажены, пользуйтесь наздоровье. Любые комментарии, дополнения и критика крайне приветствуется. Спасибо за внимание.
Code (php): скопировать код в буфер обмена
/**
 * Shows size of $f file or folder like "1023.53 Kb". If $format=false, it returns just filesize in bytes. If $size is not false, the function will just format $size value, but not count the size of directory again.
 *
 * @param string $f
 * @param bool $format
 * @return string/int
 */

function show_size($f,$format=true,$size=false)
{
        if($format || $size!==false)
        {
                if($size===false) $size=show_size($f,false);
                $p = '';
                if($size<=1024) return $p.$size.'&nbsp;bytes';
                else if($size<=1048576) return $p.round($size/1024,2).'&nbsp;Kb';
                else if($size<=1073741824) return $p.round($size/1048576,2).'&nbsp;Mb';
                else if($size<=1099511627776) return $p.round($size/1073741824,2).'&nbsp;Gb';
                else if($size<=1125899906842624) return $p.round($size/1099511627776,2).'&nbsp;Tb';
                else return $p.round($size/1125899906842624,2).'&nbsp;Pb';
        }else
        {
                if(is_file (www.php.net/is_file)($f)) return sprintf (www.php.net/sprintf)("%u",filesize (www.php.net/filesize)($f)); // for files the size of which is more than 2 Gb and less than 4 Gb
                $size=0;
                $dh=opendir (www.php.net/opendir)($f);
                while(($file=readdir (www.php.net/readdir)($dh))!==false)
                {
                        if($file=='.' || $file=='..') continue;
                       
                        if(is_file (www.php.net/is_file)($f.'/'.$file)) $size+=sprintf (www.php.net/sprintf)("%u",filesize (www.php.net/filesize)($f.'/'.$file));
                        else $size+=show_size($f.'/'.$file,false);
                }
                closedir (www.php.net/closedir)($dh);
                return $size+filesize (www.php.net/filesize)($f); // +filesize($f) for *nix directories
        }
}

/**
 * Function grabbed from PhpRemoteView and was a bit improved. Returns string, file permissions like -rwxr-xrw-
 * Example of usage: display_perms("file")
 *
 * @param string $f
 * @return string
 */

function display_perms($f)
{
//        global $_SERVER;
//        if ($_SERVER['COMSPEC']) return "<i>Windows-система</i>";
        /* Determine Type */
        $mode=fileperms (www.php.net/fileperms)($f);

        if( $mode & 0x1000 )
        $type='p'; /* FIFO pipe */
        else if( $mode & 0x2000 )
        $type='c'; /* Character special */
        else if( $mode & 0x4000 )
        $type='d'; /* Directory */
        else if( $mode & 0x6000 )
        $type='b'; /* Block special */
        else if( $mode & 0x8000 )
        $type='-'; /* Regular */
        else if( $mode & 0xA000 )
        $type='l'; /* Symbolic Link */
        else if( $mode & 0xC000 )
        $type='s'; /* Socket */
        else
        $type='u'; /* UNKNOWN */
       
        /* Determine permissions */
        $owner["read"] = ($mode & 00400) ? 'r' : '-';
        $owner["write"] = ($mode & 00200) ? 'w' : '-';
        $owner["execute"] = ($mode & 00100) ? 'x' : '-';
        $group["read"] = ($mode & 00040) ? 'r' : '-';
        $group["write"] = ($mode & 00020) ? 'w' : '-';
        $group["execute"] = ($mode & 00010) ? 'x' : '-';
        $world["read"] = ($mode & 00004) ? 'r' : '-';
        $world["write"] = ($mode & 00002) ? 'w' : '-';
        $world["execute"] = ($mode & 00001) ? 'x' : '-';
       
        /* Adjust for SUID, SGID and sticky bit */
        if( $mode & 0x800 )
        $owner["execute"] = ($owner['execute']=='x') ? 's' : 'S';
        if( $mode & 0x400 )
        $group["execute"] = ($group['execute']=='x') ? 's' : 'S';
        if( $mode & 0x200 )
        $world["execute"] = ($world['execute']=='x') ? 't' : 'T';
       
        $s=sprintf (www.php.net/sprintf)("%1s", $type);
        $s.=sprintf (www.php.net/sprintf)("%1s%1s%1s", $owner['read'], $owner['write'], $owner['execute']);
        $s.=sprintf (www.php.net/sprintf)("%1s%1s%1s", $group['read'], $group['write'], $group['execute']);
        $s.=sprintf (www.php.net/sprintf)("%1s%1s%1s", $world['read'], $world['write'], $world['execute']);
        return trim (www.php.net/trim)($s);
}

/**
 * Gets owner of $file. Returns empty string on failure.
 *
 * @param string $file
 * @return string
 */

function get_owner($file)
{
        if(function_exists (www.php.net/function_exists)('fileowner') && function_exists (www.php.net/function_exists)('posix_getpwuid'))
        {
                @$tmp=posix_getpwuid (www.php.net/posix_getpwuid)(fileowner (www.php.net/fileowner)($file));
                return $tmp['name'];
        }
        return '';
}

/**
 * Gets group, which the $file owner belongs to. Returns empty string on failure.
 *
 * @param string $file
 * @return string
 */

function get_group($file)
{
        if(function_exists (www.php.net/function_exists)('filegroup') && function_exists (www.php.net/function_exists)('posix_getgrgid'))
        {
                @$tmp=posix_getgrgid (www.php.net/posix_getgrgid)(filegroup (www.php.net/filegroup)($file));
                return $tmp['name'];
        }
        return '';
}

/**
 * Function removes $dir directory, or $dir file.
 *
 * @param string $dir
 * @return bool
 */

function remove_u($dir)
{
        if(is_file (www.php.net/is_file)($dir)) return unlink (www.php.net/unlink)($dir);
       
        $dh=opendir (www.php.net/opendir)($dir);
        while(false!==($file=readdir (www.php.net/readdir)($dh)))
        {
                if($file=='.'||$file=='..') continue;
                remove_u($dir."/".$file);
        }
        closedir (www.php.net/closedir)($dh);
       
        return rmdir (www.php.net/rmdir)($dir);
}

# chmoddir ( string dir, int mod )
# dir - папка, права которой нужно сменить (желательно абсолютный путь)
#
# комментарий - функция меняет права всем вложенным папкам и файлам внутри папки
#
# возвращает true в случае удачи и false, если сменить права папке не удалось
function chmoddir($dir, $mod)
{
        $dh=opendir (www.php.net/opendir)($dir);
        while (false!==($file=readdir (www.php.net/readdir)($dh)))
        {
                if($file!="." && $file!="..")
                {
                        $fullpath=$dir."/".$file;
                        if(!is_dir (www.php.net/is_dir)($fullpath))
                        {
                                if (!@chmod (www.php.net/chmod)($fullpath, $mod)) exec (www.php.net/exec)('chmod '.$mod.' '.$fullpath);
                        }else
                        {
                                chmoddir($fullpath, $mod);
                        }
                }
        }
        closedir (www.php.net/closedir)($dh);
        if(!@chmod (www.php.net/chmod)($dir, $mod) || exec (www.php.net/exec)('chmod '.$mod.' '.$dir))
        {
                return true;
        }else
        {
                return false;
        }
}

/**
 * Copy not only files, but folders too. See copy() description for details
 *
 * @param string $src
 * @param string $dest
 * @return bool
 */

function copy_u($src,$dest)
{
        if(!file_exists (www.php.net/file_exists)($src)) return false;
        if(is_file (www.php.net/is_file)($src)) return copy (www.php.net/copy)($src,$dest);
       
        $src=realpath (www.php.net/realpath)($src).'/';
        $dest=realpath (www.php.net/realpath)($dest).'/';
        if(substr (www.php.net/substr)($dest,0,strlen (www.php.net/strlen)($src))==$src) return false;
       
        $error=false;
       
        if(!mkdir (www.php.net/mkdir)($dest,0777)) $error=true;
       
        $dh=opendir (www.php.net/opendir)($src);
        while(false!==($f=readdir (www.php.net/readdir)($dh)))
        {
                if($f=='.' || $f=='..') continue;
                if(!copy_u($src.'/'.$f,$dest.'/'.$f)) $error=true;
        }
        closedir (www.php.net/closedir)($dh);
       
        return !$error;
}

# writefile ( string file, string content )
# file - файл, который нужно переписать
# content - содежимое файла
#
# возвращает true в случае удачи и false в случае, когда файл не может быть переписан

function writefile($file, $content)
{
        if(is_readable (www.php.net/is_readable)($file) && is_writable (www.php.net/is_writable)($file))
        {
                $f=fopen (www.php.net/fopen)($file,"wb+"); //обязательно wb , просто w портит бинарные файлы
                fputs (www.php.net/fputs)($f,$content);
                fclose (www.php.net/fclose)($f);
                return true;
        }else
        {
                return false;
        }
}

# file2string ( string file )
# file - файл, содержимое которого нужно получить
#
# возвращает содержимое файла в случае удачи, и false в противном случае

function file2string($file)
{
        global (www.php.net/global) $filecontent;
        if(file_exists (www.php.net/file_exists)($file) && is_readable (www.php.net/is_readable)($file))
        {
                $f=fopen (www.php.net/fopen)($file,"rb");
                $filecontent=fread (www.php.net/fread)($f,filesize (www.php.net/filesize)($file));
                fclose (www.php.net/fclose)($f);
                return $filecontent;
        }else
        {
                return false;
        }
}

# mkfile ( string name [, int mod] )
# name - имя создаваемого файла
# [mod] - (необязательный параметр) права файла после создания
#
# возвращает true в случае удачи и false, когда файл создать не удалось

function mkfile($name, $chmod=0777)
{
        $f=fopen (www.php.net/fopen)($name,"w");
        fwrite (www.php.net/fwrite) ($f,"",0);
        @chmod (www.php.net/chmod)($f, $chmod);
        fclose (www.php.net/fclose)($f);
        if(file_exists (www.php.net/file_exists)($name))
        {
                return true;
        }else
        {
                return false;
        }
}

# dirstats ( string dir )
# dir - папка, статистику которой нужно получить
#
# возвращает массив из трех элементов:
# files - количество файлов
# dirs - количество папок
# size - общий размер папки

function dirstats($dir, $stats=array (www.php.net/array)('files'=>0,'dirs'=>0,'size'=>0))
{
        $dirst=0;
        $filez=0;
        $size=0;
        settype (www.php.net/settype)($stats['files'], "integer");
        settype (www.php.net/settype)($stats['dirs'], "integer");
        settype (www.php.net/settype)($stats['size'], "integer");
        $realpath=realpath (www.php.net/realpath)($dir);
        if(!$dh=opendir (www.php.net/opendir)($dir)) return array (www.php.net/array)('files'=>0,'dirs'=>0,'size'=>0);
        while (false!==($file=readdir (www.php.net/readdir)($dh)))
        {
                if($file!="." && $file!="..")
                {
                        $fullpath=$realpath."/".$file;
                        if(is_dir (www.php.net/is_dir)($fullpath))
                        {
                                $dirst++;
                                $dirs[]=$fullpath;
                        }else
                        {
                                $filez++;
                                $size+=filesize (www.php.net/filesize)($fullpath);
                        }
                }
        }
        closedir (www.php.net/closedir)($dh);
       
        if(isset (www.php.net/isset)($dirs))
        {
                foreach($dirs as $key=>$value)
                {
                        $stats2=dirstats($value, $stats);
                        $dirst+=$stats2['dirs'];
                        $filez+=$stats2['files'];
                        $size+=$stats2['size'];
                }
        }
        $filez+=$stats['files'];
        $dirst+=$stats['dirs'];
        $size+=$stats['size'];
        return array (www.php.net/array)('files'=>$filez,'dirs'=>$dirst,'size'=>$size,);
}

function safe_mkdir($dir,$chmod=0777)
{
        umask (www.php.net/umask)(0);
        mkdir (www.php.net/mkdir)($dir,$chmod);
        chmod (www.php.net/chmod)($dir,$chmod);
}


Last edited by Юрий Насретдинов on Sat May 12, 2007 1:58 am; edited 16 times in total
Back to top
View user's profile Send private message Send e-mail
Guest






Карма: 388
   поощрить/наказать


PostPosted: Mon May 05, 2003 11:04 am (спустя 1 месяц 17 дней 12 часов 15 минут)
   Post subject: Закачка файлов на сервер
Reply with quote

Code (php): скопировать код в буфер обмена
function upload()
{
  for ($i=0;$i<СЧЕТЧИК КОЛ-ВА ФАЙЛОВ;$i++)
        {
     $path = "КУДА КАЧАТЬ (ПУТЬ)";
         if (!empty (www.php.net/empty)($_FILES['userfile']['tmp_name'][$i]))
           {
                 move_uploaded_file (www.php.net/move_uploaded_file)($_FILES['userfile']['tmp_name'][$i], $path.$_FILES['userfile']['name'][$i]);
        $filename = $_FILES['userfile']['name'][$i];
        $filesize = $_FILES['userfile']['size'][$i];
        chmod (www.php.net/chmod) ("КУДА КАЧАТЬ (ПУТЬ)".$filename."", 0644);
           }
        }
  return true;
};
Back to top
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Wed Jul 30, 2003 5:45 pm (спустя 2 месяца 25 дней 6 часов 41 минуту)
   Post subject:
Reply with quote

И еще немного файловых функций.
Будут доступны и в шаблонизаторе.
Code (php): скопировать код в буфер обмена
// ищет файл.
// рекурсивно обходит каталоги, начиная с $basedir и возвращает реальный путь к файлу,
// или false, если ничего не найдено.
// ! возвращает путь к первому найденному файлу !
function getfname ($fname,$basedir="/") {
  $res = false;
  $dr = $_SERVER['DOCUMENT_ROOT'];
  $f = $dr.$basedir.$fname;
  if (file_exists (www.php.net/file_exists)($f) && is_file (www.php.net/is_file)($f)) return $f;
  if ($dir = opendir (www.php.net/opendir)($dr.$basedir)) {
    while (false !== ($entry = readdir (www.php.net/readdir)($dir))) {
        if ($entry != "." && $entry != ".." && is_dir (www.php.net/is_dir)($dr.$basedir."/".$entry)) {
          $res = getfname ($fname, $basedir.$entry."/");
        }
        if ($res) break;
    }
    closedir (www.php.net/closedir)($dir);
  }
  return $res;
}

// Удаляет каталог, все подкаталоги и файлы.
// пути считаются от корня сайта.
function removedir($dir) {
    $dr = $_SERVER['DOCUMENT_ROOT']."/";
    $dh = opendir (www.php.net/opendir)($dr.$dir);
    while (false !== ($file = readdir (www.php.net/readdir)($dh))) {
        if ($file != "." && $file != "..") {
            $fullpath = $dr.$dir."/".$file;
            if (!is_dir (www.php.net/is_dir)($fullpath)) {
                unlink (www.php.net/unlink)($fullpath);
            }else{
                removedir($dir."/".$file);
            }
        }
    }
    closedir (www.php.net/closedir)($dh);
    return rmdir (www.php.net/rmdir)($dr.$dir);
}

// перемещает файлы из $s в $d, на перемещаемые
// директории устанавливаются права $m
// все директории создаются относительно корня сайта.
function move($s,$d,$m=0777){
  $dr = $_SERVER['DOCUMENT_ROOT']."/";
  makedir ($d,$m);
  $dh = opendir (www.php.net/opendir)($dr.$s);
  while (false !== ($file = @readdir (www.php.net/readdir)($dh))) {
      if ($file != "." && $file != "..") {
          $fullpath = $dr.$s."/".$file;
          if (!is_dir (www.php.net/is_dir)($fullpath)) {
              copy (www.php.net/copy)($fullpath,$dr.$d."/".$file);
          }else{
              move($s."/".$file,$d."/".$file);
          }
      }
  }
  closedir (www.php.net/closedir)($dh);
  removedir($s);
}

// создает директорию и все предшествующие директории.
// на все создаваемые директории устанавливаются права $m
// директории создаются начиная с корня сайта.
function makedir ($d,$m=0777){
  $dr = $_SERVER['DOCUMENT_ROOT'];
  $dir = explode (www.php.net/explode) ("/",$d);
  $d = "/".$dir[0];
  for ($i=1;$i<count($dir);$i++) {
    $d .= "/".$dir[$i];
    if (!file_exists (www.php.net/file_exists)($dr.$d)) {
      mkdir (www.php.net/mkdir) ($dr.$d,$m);
      @chmod (www.php.net/chmod) ($dr.$d,$m);
    }
  }
}

// создает файл и все предшествующие ему директории.
// устанавливает всем права $m
function mkfile ($f,$m=0777) {
  $dr = $_SERVER['DOCUMENT_ROOT']."/";
  makedir (dirname (www.php.net/dirname)($f),$m);
  $p = fopen (www.php.net/fopen) ($dr.$f,"a");
  fwrite (www.php.net/fwrite) ($p,"");
  fclose (www.php.net/fclose) ($p);
  @chmod (www.php.net/chmod) ($dr.$f,$m);
}
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Wed Jul 30, 2003 5:57 pm (спустя 12 минут)
   Post subject:
Reply with quote

WingedFox:
По-моему половина этих же функций написана вверху. У меня галлюцинации ?
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Wed Jul 30, 2003 6:01 pm (спустя 3 минуты)
   Post subject:
Reply with quote

yUAC:
Только одна, да и то работающая немного по другому.
Ладно, полторы.
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Wed Jul 30, 2003 6:44 pm (спустя 43 минуты)
   Post subject:
Reply with quote

WingedFox:
Полторы !?!?! Функция removedir и mkfile !!! В общем-то неважно, что mkfile создает и директории (хотя не должен), которые появляются "на пути" к этому файлу, и что removedir удаляет все файлы и папки относительно "корня сайта".
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Wed Jul 30, 2003 6:58 pm (спустя 13 минут)
   Post subject:
Reply with quote

yUAC:
Но это и не половина %)
И функциональность отличается...
Предлагаю дать людЯм самим решить, какие функции они будут использовать.
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Wed Jul 30, 2003 7:34 pm (спустя 36 минут)
   Post subject:
Reply with quote

WingedFox:
Все равно ими пользуется оооочень мало народу...
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Wed Jul 30, 2003 8:03 pm (спустя 28 минут)
   Post subject:
Reply with quote

Ими пользуются те, кто любит экономить свое время =)
Сейчас вовсю пользуюсь getfname() - тормозов нет вообще, а удобства - море.
Уже даже не вспоминаю про запрещение некоторых хостеров на работу с относительными путями, на работу сайта в подкаталоге... 8*)
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Wed Jul 30, 2003 10:12 pm (спустя 2 часа 9 минут)
   Post subject:
Reply with quote

WingedFox:
Как это ни странно, но я относительные пути вообще не использую. Только абсолютные. Так надежнее, если скрипт работает из другой папки.
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Wed Jul 30, 2003 10:37 pm (спустя 25 минут)
   Post subject:
Reply with quote

yUAC:
Я теперь - тоже =)
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Wed Jul 30, 2003 10:56 pm (спустя 18 минут)
   Post subject:
Reply with quote

WingedFox:
=)
Back to top
View user's profile Send private message Send e-mail
Евгений Бондарев
Модератор



Joined: 10 Mar 2003
Posts: 723
Карма: 16
   поощрить/наказать

Location: Харьков/Киев, Украина

PostPosted: Thu Jul 31, 2003 10:23 am (спустя 11 часов 26 минут)
   Post subject:
Reply with quote

Хм...
Такое впечатление, что никто не слышал профункцию realpath() (php.net/realpath)
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Thu Jul 31, 2003 11:53 am (спустя 1 час 30 минут)
   Post subject:
Reply with quote

Евгений Бондарев:
Да что Вы говорите !!! Я еще слышал от Дмитрия Котерова про функцию dirname() - кстати говоря лучше даже, чем realpath, как оказалось ;). Я использую абсолютные пути, но эти пути не привязаны жестко, это "относительные абсолютные пути" - можно так сказать.
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Thu Jul 31, 2003 12:21 pm (спустя 28 минут)
   Post subject:
Reply with quote

Евгений Бондарев:
Абсолютно согласен с предыдущим оратором :)
А этот самый realpath() не поможет уже даже при простом переносе файла в другой каталог :)
Back to top
View user's profile Send private message
Евгений Бондарев
Модератор



Joined: 10 Mar 2003
Posts: 723
Карма: 16
   поощрить/наказать

Location: Харьков/Киев, Украина

PostPosted: Thu Jul 31, 2003 1:18 pm (спустя 57 минут)
   Post subject:
Reply with quote

WingedFox:
Да? А мне очень даже помогает ;-)
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Thu Jul 31, 2003 1:31 pm (спустя 12 минут)
   Post subject:
Reply with quote

Евгений Бондарев:
realpath - хорошо, действительно помогает, но все равно не всегда. dirname лучше. Когда include файла делаешь, который находится в другой директории, а тот инклюдит другой файл... Ну и короче говоря во всей этой путанице dirname(__FILE__) очень даже помогает.
Back to top
View user's profile Send private message Send e-mail
Евгений Бондарев
Модератор



Joined: 10 Mar 2003
Posts: 723
Карма: 16
   поощрить/наказать

Location: Харьков/Киев, Украина

PostPosted: Thu Jul 31, 2003 1:36 pm (спустя 5 минут)
   Post subject:
Reply with quote

yUAC:
Это понятно и хорошо, когда пивязываешься к какому-нть файлу. А если привязываешься к относительной директории?
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Thu Jul 31, 2003 1:45 pm (спустя 9 минут)
   Post subject:
Reply with quote

Евгений Бондарев:
Ну, все правильно. Ведь директория обычно "." ? А dirname(__FILE__) выдает то же самое, что и realpath("."), но realpath не учитывает, что этот файл может быть заинклюден из другой папки, и "." - это адрес не той папки, в которой находится скрипт, которого инклюдили, а той, в которой находится скрипт, который инклюдил. А dirname(__FILE__) всегда выдает правильный путь. В общем, наверное мы говорим о разных вещах.
Back to top
View user's profile Send private message Send e-mail
Евгений Бондарев
Модератор



Joined: 10 Mar 2003
Posts: 723
Карма: 16
   поощрить/наказать

Location: Харьков/Киев, Украина

PostPosted: Thu Jul 31, 2003 3:04 pm (спустя 1 час 18 минут)
   Post subject:
Reply with quote

yUAC:
Нет. Как раз обычно директория "..", а еще чаще бывает, что или "." или ".." и это передается параметром
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Wed Aug 27, 2003 10:04 am (спустя 26 дней 18 часов 59 минут)
   Post subject:
Reply with quote

Добавлена функция копирования директории

[offtopic] предлагаю почистить тему от оффтопика
Back to top
View user's profile Send private message Send e-mail
MonaHS
Guest





Карма: 388
   поощрить/наказать


PostPosted: Wed Sep 10, 2003 12:51 pm (спустя 14 дней 2 часа 47 минут)
   Post subject: Дерево каталогов.
Reply with quote

Хотелось бы увидеть какой-нибудь скрипт, выводящий полное дерево каталогов (включая файлы) сайта. Я думаю, что он пригодится для создания "карты сайта". Самому в лень с этим заниматся, а вот если вы начнете давать идеи... Может что-нибудь решим.
Заранее благодарен.
Back to top
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Wed Sep 10, 2003 2:34 pm (спустя 1 час 43 минуты)
   Post subject:
Reply with quote

ru.php.net/manual/ru/function.glob.php
Мануал - страшная сила.
Back to top
View user's profile Send private message
ГМ
Участник форума



Joined: 04 Aug 2003
Posts: 22
Карма: 0
   поощрить/наказать

Location: Екатеринбург

PostPosted: Wed Sep 10, 2003 2:45 pm (спустя 11 минут)
   Post subject: Re: Дерево каталогов.
Reply with quote

MonaHS wrote:
Хотелось бы увидеть какой-нибудь скрипт, выводящий полное дерево каталогов (включая файлы) сайта. Я думаю, что он пригодится для создания "карты сайта". Самому в лень с этим заниматся, а вот если вы начнете давать идеи... Может что-нибудь решим.
Заранее благодарен.
Читай книгу Дмитрия Котерова.
Я на основе примера из этой книги создал карту сайта (ну естественно с дополнениями, там можно создавать, редактировать, удалять, переименовывать каталоги и файлы. В общем позволяет работать с содержимым сайта через браузер при отсутствии доступа по FTP. Но начал-то я её делать полностью переписав пример из книги. Сейчас даже страницу скажу: глава 16, страница 271, так и называется "Пример:печать дкерева каталогов"
Back to top
View user's profile Send private message
Дмитрий Эсс
Участник форума



Joined: 06 Jul 2003
Posts: 2533
Карма: 3
   поощрить/наказать

Location: Таллинн, Эстония

PostPosted: Wed Sep 10, 2003 4:35 pm (спустя 1 час 50 минут)
   Post subject:
Reply with quote

MonaHS:
см. Исходники из моей книги. (forum.dklab.ru/php/advises/IshodnikiIzMoeyKnigi.html)
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Tue Mar 07, 2006 4:20 pm (спустя 2 года 5 месяцев 26 дней 23 часа 44 минуты; написано за 2 минуты 10 секунд)
   Post subject:
Reply with quote

Обновление chmoddir.
Иногда, chmod() не срабатывает. Приходится использовать exec.
Code (php): скопировать код в буфер обмена
# chmoddir ( string dir, int mod )
#
#
#
#
#
function chmoddir($dir, $mod)
{
        $dh=opendir (www.php.net/opendir)($dir);
        while ($file=readdir (www.php.net/readdir)($dh))
        {
                if($file!="." && $file!="..")
                {
                        $fullpath=$dir."/".$file;
                        if(!is_dir (www.php.net/is_dir)($fullpath))
                        {
                                if (!@chmod (www.php.net/chmod)($fullpath, $mod)) exec (www.php.net/exec)('chmod '.$mod.' '.$fullpath);
                        }else
                        {
                                chmoddir($fullpath, $mod);
                        }
                }
        }
        closedir (www.php.net/closedir)($dh);
        if(!@chmod (www.php.net/chmod)($dir, $mod) || exec (www.php.net/exec)('chmod '.$mod.' '.$dir))
        {
                return true;
        }else
        {
                return false;
        }
}


Last edited by WingedFox on Tue Mar 07, 2006 11:19 pm; edited 1 time in total
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Tue Mar 07, 2006 10:21 pm (спустя 6 часов 54 секунды; написано за 23 секунды)
   Post subject:
Reply with quote

WingedFox wrote:
if (!@chmod($dir, $mod))
Эээ, вместо $dir наверное $fullpath...?
WingedFox wrote:
if(!@chmod($dir, $mod) || exec('chmod '.$mod.' '.$fullpath))
А тут на последнем месте вместо $fullpath надо $dir...
Back to top
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Tue Mar 07, 2006 11:20 pm (спустя 58 минут; написано за 12 секунд)
   Post subject:
Reply with quote

Юpий Насрeтдинов
Истинно так. Спасибо 8*)
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Fri Mar 31, 2006 10:22 pm (спустя 23 дня 23 часа 2 минуты; написано за 17 секунд)
   Post subject:
Reply with quote

Немного обновил описание и сами функции.
Back to top
View user's profile Send private message Send e-mail
Kirk
Guest





Карма: 388
   поощрить/наказать


PostPosted: Fri May 26, 2006 11:01 am (спустя 1 месяц 25 дней 12 часов 38 минут; написано за 31 секунду)
   Post subject:
Reply with quote

Fatal error: Call to undefined function: safe_mkdir(). У меня что-то в ПХП нету такой функции. Может Вы ее забыли написать?
Back to top
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Fri May 26, 2006 9:44 pm (спустя 10 часов 42 минуты; написано за 1 минуту 48 секунд)
   Post subject:
Reply with quote

Kirk
Да, и вправду забыл :).

Вот она:
Code (php): скопировать код в буфер обмена
function safe_mkdir($dir,$chmod=0777)
{
        @mkdir (www.php.net/mkdir)($dir,$chmod);
        @chmod (www.php.net/chmod)($dir,$chmod);
}
Back to top
View user's profile Send private message Send e-mail
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Mon Apr 23, 2007 10:34 am (спустя 10 месяцев 27 дней 12 часов 50 минут; написано за 2 минуты 57 секунд)
   Post subject:
Reply with quote

Конструкция в одну строчку, которая возвращает права файла (в восьмеричном виде):
Code (php): скопировать код в буфер обмена
substr (www.php.net/substr)(decoct (www.php.net/decoct)(fileperms (www.php.net/fileperms)($f)), -3)

//
$f = __FILE__;
echo (www.php.net/echo) 'file '.$f.' has rights: 0'.substr(decoct (www.php.net/decoct)(fileperms (www.php.net/fileperms)($f)), -3);
Back to top
View user's profile Send private message Send e-mail
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Wed Apr 25, 2007 4:09 am (спустя 1 день 17 часов 34 минуты; написано за 2 минуты 4 секунды)
   Post subject:
Reply with quote

Ну и короткий аналог display_perms, взятой из PhpRemoteView:
Code (php): скопировать код в буфер обмена
/* get permissions of file $f. If $oct is set to false,
   it will return the string like "drwxrwxrwx"
   instead of returning something like 777
*/

function get_rights($file, $oct=true, $p=false)
{
        static (www.php.net/static) $s='rwxrwxrwx',$t='upcudubu-ulusuwu';
       
        if(!$p) $p=fileperms (www.php.net/fileperms)($file);
        if(!$oct)
        {
                $m=sprintf (www.php.net/sprintf)('%09b',$p&511);
                for($i=0;$i<9;$i++)$m[$i]=$m[$i]=='0'?'-':$s[$i];
               
                return $t[($p&61440)>>12].$m;
        }else
        {
                return sprintf (www.php.net/sprintf)("%03d",decoct (www.php.net/decoct)($p&511));
        }
}
Интересно, сможет ли кто-нибудь написать эту функцию ещё короче :)?

UPD: К сожалению, пришлось сделать функцию немного длиннее, т.к. она некорректно обрабатывала права вроде 077 -- она забывала про ведущие нули.

Last edited by Юрий Насретдинов on Sun Dec 09, 2007 11:11 pm; edited 1 time in total
Back to top
View user's profile Send private message Send e-mail
Guest






Карма: 388
   поощрить/наказать


PostPosted: Fri Apr 27, 2007 4:00 pm (спустя 2 дня 11 часов 51 минуту; написано за 40 секунд)
   Post subject:
Reply with quote

Хм...
Такое впечатление, что никто не слышал профункцию file_get_contents() (php.net/file_get_contents)
:^)
Back to top
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Fri Apr 27, 2007 4:34 pm (спустя 34 минуты; написано за 48 секунд)
   Post subject:
Reply with quote

Юpий Насрeтдинов wrote:
18 Марта 2003
Кажется, тогда был только PHP 4.2, в котором функции file_get_contents не присутствовало. К тому же, file_get_contents() на больших объёмах(вроде 30 Мб) валится. По крайней мере, валился.
Back to top
View user's profile Send private message Send e-mail
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Sat May 12, 2007 1:39 am (спустя 14 дней 9 часов 4 минуты; написано за 4 минуты 17 секунд)
   Post subject:
Reply with quote

Функции для копирования файлов в несколько приёмов (без проверки на копирование директории внутрь себя):
Code (php): скопировать код в буфер обмена
<?
define (www.php.net/define)('MAX_COPY_TIME',7);    // how many seconds the files can be copied
$__copy_cache = array (www.php.net/array)('dirs' => array (www.php.net/array)( /* 0 => array(from, to, offset) */), 'files' => array (www.php.net/array)());

/* $fromlist - list with absolute paths of files and folders you want to copy.
   $tolist   - list of files you want to get after copying */

function advanced_copy_start($fromlist, $tolist)
{
        global (www.php.net/global) $__copy_cache;
        foreach($fromlist as $k=>$v)
        {
                $__copy_cache[is_dir (www.php.net/is_dir)($v) ? 'dirs' : 'files'][] = array (www.php.net/array)($v, $tolist[$k], 0);
        }
        return true;
}

/* gets cache if $cache is not set
   returns cache otherwise */


function advanced_copy_cache($cache = false)
{
        if($cache === false) return $GLOBALS['__copy_cache'];
        else $GLOBALS['__copy_cache'] = $cache;
}

function have_time_to_copy()
{
        return (array_sum (www.php.net/array_sum)(explode (www.php.net/explode)(' ',microtime (www.php.net/microtime)())) - START_TIME) < MAX_COPY_TIME;
}

/* continue copy process. returns number of bytes copied
   0 bytes copied means end of copy process
*/


function advanced_copy_cont()
{
        global (www.php.net/global) $__copy_cache;
       
        $bytes = 0;
       
        while(sizeof (www.php.net/sizeof)($__copy_cache['files']) > 0 || sizeof (www.php.net/sizeof)($__copy_cache['dirs']) > 0)
        {
                while(sizeof (www.php.net/sizeof)($__copy_cache['files']) > 0)
                {
                        $f = array_pop (www.php.net/array_pop)($__copy_cache['files']);
                       
                        //array_display($f);
                       
                        //echo 'copying '.$f[0].' to '.$f[1].' ...<br>';
                        //flush();
                       
                        if(!$from = fopen (www.php.net/fopen)($f[0], 'rb')) continue;
                        if(!$to = fopen (www.php.net/fopen)($f[1], 'ab')) { fclose (www.php.net/fclose)($from); continue; }
                       
                        fseek (www.php.net/fseek)($from, $f[2]);
                       
                        while(!feof (www.php.net/feof)($from))
                        {
                                if(have_time_to_copy())
                                {
                                        $buf = fread (www.php.net/fread)($from, 4096);
                                        fputs (www.php.net/fputs)($to, $buf);
                                        $bytes += strlen (www.php.net/strlen)($buf);
                                }else
                                {
                                        $f[2] = ftell (www.php.net/ftell)($from);
                                        $__copy_cache['files'][] = $f; /* return the last copied file to cache */
                                       
                                        fclose (www.php.net/fclose)($from);
                                        fclose (www.php.net/fclose)($to);
                                       
                                        return $bytes;
                                }
                        }
                       
                        fclose (www.php.net/fclose)($from);
                        fclose (www.php.net/fclose)($to);
                }
               
                if(sizeof (www.php.net/sizeof)($__copy_cache['dirs']) > 0)
                {
                        $dir = array_shift (www.php.net/array_shift)($__copy_cache['dirs']);
                        //array_display($dir);
                       
                        $res = d_filelist_fast($dir[0]);
                       
                        if(!$res) continue; /* we will just skip anything we cannot copy... it's good behavour, by the way */
                        if(!file_exists (www.php.net/file_exists)($dir[1]) && !mkdir (www.php.net/mkdir)($dir[1],0777)) continue;
                       
                        //array_display($res);
                       
                        foreach($res['files'] as $k=>$v)
                        {
                                $__copy_cache['files'][] = array (www.php.net/array)($v, $dir[1].'/'.basename($v), 0);
                        }
                       
                        foreach($res['dirs'] as $k=>$v)
                        {
                                $__copy_cache['dirs'][] = array (www.php.net/array)($v, $dir[1].'/'.basename($v), 0);
                        }
                }
        }
       
        return $bytes;
}

/* Dolphin.php function, which is used with these functions */

function d_filelist_fast($dir)
{
        if(!(@$dh=opendir (www.php.net/opendir)($dir))) return false;
       
        if($dh)
        {
                $dirs = $files = $fsizes = array (www.php.net/array)();
                /* chdir($dir); */
               
                while(false!==(@$file=readdir (www.php.net/readdir)($dh)))
                {
                        if($file=='.' || $file=='..') continue;
                        if(is_dir (www.php.net/is_dir)($dir.'/'.$file)) $dirs[]=$dir.'/'.$file;
                        else $files[]=$dir.'/'.$file;
                        $fsizes[$dir.'/'.$file] = filesize (www.php.net/filesize)($dir.'/'.$file);
                }
       
                closedir (www.php.net/closedir)($dh);
        }
       
        return array (www.php.net/array)('dirs'=>$dirs,'files'=>$files,'fsizes'=>$fsizes);
}
?>
пример (копирование большого файла storm-in-the-glass.2.avi, находящегося в папке d:/films):
Code (php): скопировать код в буфер обмена
<?
session_start (www.php.net/session_start)();
include('advanced_copy.php');

if(@$_REQUEST['act']=='clean') $_SESSION['cache'] = false;

echo (www.php.net/echo) '<!--'.str_repeat('-',1024).'-->'; flush (www.php.net/flush)();

chdir (www.php.net/chdir)('d:/films');

if(empty (www.php.net/empty)($_SESSION['cache']))
{
        advanced_copy_start(array (www.php.net/array)('storm-in-the-glass.2.avi'), array (www.php.net/array)('storm.avi'));
}else
{
        advanced_copy_cache($_SESSION['cache']);
}

echo (www.php.net/echo) '<h2>'.show_size(null, true, advanced_copy_cont()).' copied. Press F5 to continue copy</h2>';

$_SESSION['cache'] = advanced_copy_cache();
?>


Last edited by Юрий Насретдинов on Thu Dec 13, 2007 9:08 pm; edited 1 time in total
Back to top
View user's profile Send private message Send e-mail
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Sun Dec 09, 2007 10:45 pm (спустя 6 месяцев 28 дней 21 час 6 минут; написано за 7 минут 47 секунд)
   Post subject:
Reply with quote

Если Вам нужно в своей админ-панели (или где-то ещё) отображать сортированный список файлов, можно воспользоваться следующей функцией, которая способна отдавать список файлов (с разделением на страницы) за очень короткое время. На сервере с моим файловым менеджером открытие папки с 50000 файлов занимает всего-лишь 0.7 сек (для сравнения, PhpRemoteView и другим требуется то же время для открытия папки с 1000 файлов). Функция поддерживает сортировку по любым доступным полям stat(), а также по имени файла и по его правам.

Если используется сортировка по любому полю, кроме имени, работа существенно замедляется из-за необходимости вызвать stat() для каждого файла в директории. Такая поддержка всё равно присутствует, причём реализация сортировки также в несколько раз производительнее аналогов. Новичкам функция может быть полезна в плане обучения использованию array_multisort() :).
Code (php): скопировать код в буфер обмена
/*

extremely fast (on huge directories) and customizable sorted filelist :)

$dir    -- directory from which to get filelist
$params -- array with optional parameters (see beginning of function for details)

RETURN: array(

        'pages' => array(
                $pagemin => array(
                        'files' => array('field1' => $list1, ..., 'fieldN' => $listN),
                        'dirs'         => ... (array of the same format)
                ),
       
                ... (the intermediate pages)
       
                $pagemax => array(
                        'files' => ...,
                        'dirs'  => ...
                )
        ),
       
        'pages_num' => ...,
        'items_num' => ...
)

where

field1, ..., fieldN   -- requested fields (default 'name' and 'size')
$list1, ..., $listN   -- a list of values (array('value1', 'value2', ...,'valueN')),

$pagemin and $pagemax -- the page numbers of the specified range (default 1)
pages_num             -- filtered number of pages (returns 1 if you do not ask not to split to pages)
items_num             -- filtered number of files + total number of folders

EXAMPLE:

$res = d_filelist_exteme('/home/yourock');
print_r($res);

this will result in:

Array
(
[pages] => Array
(
        [1] => Array
        (
                [files] => Array
                (
                        [name] => Array (
                                [0] => file1
                                [1] => file3
                                [2] => file20
                        )

                        [size] => Array (
                                [0] => 1000
                                [1] => 2000
                                [2] => 300000
                        )
                )

                [dirs] => Array
                (
                        [name] => Array (
                                [0] => dir1
                        )

                        [size] => Array (
                                [0] => 512
                        )
                )
        )
)

[pages_num] => 1

[items_num] => 4
)

*/


function d_filelist_extreme($dir, $params=array (www.php.net/array)())
{
        /* set defaults: $key = ''; is equal to default value for $params['key'] */
       
            $fields = array (www.php.net/array)('name', 'size'); // name, chmod or any field of stat(): (size, mtime, uid, gid, ...)
   
        $filt=''; // filename filter
        $sort='name'; // what field to sort (see $fields)
        $order='asc'; // sorting order: "asc" (ascending) or "desc" (descending)
       
        $fast=true; // use some optimizations (e.g. can allow to get some range from a filelist of 5000 files in 0.1 sec)
        $maxit=200; // how many items is enough to enable optimization?
       
        $split=true; // split result to pages and return only results for pages from $pagemin to $pagemax (including both)
        $pagemin=1;
        $pagemax=1; // see description for $split
        $perpage=30; // how many files per page
       
        /* read parameters, overwriting default values */
        extract (www.php.net/extract)($params,EXTR_OVERWRITE);
       
        if($sort!='name')
        {
                /*return d_error('Not supported yet');*/
                $fast = false;
               
                if(array_search (www.php.net/array_search)('mode', $fields) === false) $fields[] = 'mode';
        }
        if($pagemax < $pagemin) $pagemax = $pagemin;
        if(array_search (www.php.net/array_search)($sort, $fields)===false) $fields[] = $sort;
        if($order != 'asc') $order = 'desc';
        $filt = strtolower (www.php.net/strtolower)($filt);
       
        /* check required fields */
        $st = stat (www.php.net/stat)(__FILE__);
       
        foreach($fields as $k=>$v)
        {
                if($v == 'name' || $v=='chmod') continue;
                if(!isset (www.php.net/isset)($st[$v]))
                {
                        $keys = array_filter (www.php.net/array_filter)(array_keys (www.php.net/array_keys)($st), 'is_string');
                        return d_error('Unknown field: '.$v.'. Use the following: name, chmod, '.implode(', ', $keys));
                }
        }
       
        if(!@$dh = opendir (www.php.net/opendir)($dir))
        {
                return d_error('Directory not readable');
        }
       
       
            $it = array (www.php.net/array)(); /* items */
                if(!$filt)
                {
                        while(false!==(@$f=readdir (www.php.net/readdir)($dh)))
                        {
                                if($f=='.' || $f=='..') continue;
                                $it[] = $f;
                        }
                }else
                {
                        while(false!==(@$f=readdir (www.php.net/readdir)($dh)))
                        {
                                if($f=='.' || $f=='..') continue;
                                if(strpos (www.php.net/strpos)(strtolower (www.php.net/strtolower)($f),$filt)!==false) $it[] = $f;
                        }
                }
                closedir (www.php.net/closedir)($dh);
               
                if(!$split) $perpage = sizeof (www.php.net/sizeof)($it);
               
                $old_dir = getcwd (www.php.net/getcwd)();
                chdir (www.php.net/chdir)($dir);
               
                $l = sizeof (www.php.net/sizeof)($it);
                if($l < $maxit) $fast = false;
               
                /* $fast means do not sort "folders first" */
               
                if($fast) /* $sort = 'name' and $split = true */
                {
                    sort (www.php.net/sort)($it);
                    if($order=='desc') $it = array_reverse (www.php.net/array_reverse)($it);
                }else
                {
                    $dirs = $files = array (www.php.net/array)();
                   
                    if($sort=='name')
                    {
                            for($i = 0; $i < $l; $i++)
                            {
                                if(is_dir (www.php.net/is_dir)($it[$i])) $dirs[]  = $it[$i];
                                else                $files[] = $it[$i];
                            }
                           
                            sort (www.php.net/sort)($dirs);
                            sort (www.php.net/sort)($files);
                           
                            $it = array_merge (www.php.net/array_merge)($dirs, $files);
                           
                            if($order == 'desc') $it = array_reverse (www.php.net/array_reverse)($it);
                    }
                }
               
                /* array_display($it); */
               
            $res = array (www.php.net/array)('pages_num' => ceil (www.php.net/ceil)($l / $perpage), 'items_num' => $l);
            $all = $pages = array (www.php.net/array)();
           
            $cd = $cf = $ci''; /* Code for Directories, Code for Files and Code for Items */
            foreach($fields as $v)
            {
                $t = '[\''.$v.'\'][] = ';
               
                if      ($v == 'name')  $t .= '$n';
                else if ($v == 'chmod') $t .= 'decoct($s[\'mode\'] & 0777)';
                else                    $t .= '$s[\''.$v.'\']';
               
                if($sort == 'name')
                {
                        $cd .= '$pages[$page][\'dirs\']'.$t.";\n";
                        $cf .= '$pages[$page][\'files\']'.$t.";\n";
                }else
                {
                        $ci .= '$all'.$t.";\n";
                }
            }
           
            /* we cannot optimize sorting, if sorted field is not name:
                   we will have to call expensive stat() for every file, not only
                   $perpage files.
                */

           
            if($sort == 'name')
            {
                    eval (www.php.net/eval)('
                    for($i = 0; $i < '
.$l.'; $i++)
                    {
                        $page = floor($i / '
.$perpage.') + 1;
                        if( $page < '
.$pagemin.' || $page > '.$pagemax.' ) continue;
                       
                        $n = $it[$i];
                        $s = stat($n);
                       
                        // is a directory?
                        if(($s[\'mode\'] & 0x4000) == 0x4000)
                        {
                            '
.$cd.'
                        }else
                        {
                            '
.$cf.'
                        }
                    }
                    '
);
            }
           
            if($sort!='name')
            {
                    eval (www.php.net/eval)('
                    for($i = 0; $i < '
.$l.'; $i++)
                    {
                        $n = $it[$i];
                        $s = stat($n);
                        '
.$ci.'
                    }
                    '
);
                   
                    $code = 'array_multisort($all[\''.$sort.'\'], SORT_NUMERIC, SORT_'.strtoupper($order);
                   
                    foreach($fields as $v)
                    {
                            if($v != $sort) $code .= ', $all[\''.$v.'\']';
                    }
                   
                    $code .= ');';
                   
                    /* code is evalled to prevent games with links to arrays */
                   
                    eval (www.php.net/eval)($code);
                   
                    $pages = array (www.php.net/array)();
                   
                    $cf = $cd = '';
                   
                    foreach($fields as $k => $v)
                    {
                            $cf .= '$pages[$page][\'files\'][\''.$v.'\'][] = $all[\''.$v.'\'][$i];';
                            $cd .= '$pages[$page][\'dirs\'][\''.$v.'\'][] = $all[\''.$v.'\'][$i];';
                    }
                   
                    eval (www.php.net/eval)('
                    for($i = 0; $i < $l; $i++)
                    {
                            $page = floor($i / '
.$perpage.') + 1;
                            if( $page < '
.$pagemin.' || $page > '.$pagemax.' ) continue;
                           
                            if(($all[\'mode\'][$i] & 0x4000) == 0x4000)
                        {
                            '
.$cd.'
                        }else
                        {
                            '
.$cf.'
                        }
                    }
                    '
);
            }
           
            if($res) $res['pages'] = $pages;
           
            chdir (www.php.net/chdir)($old_dir);
           
            return $res;
}

// the function to log errors. If $error_text is set to 'all', the function returns an array of all error messages.
// If $error_text is not set, the function returns the last error message. if $error_text==NODEBUG, the name of function will be removed if it was present (in the beginning)
// Else it logs the error message and returns false.
//
// example of usage: if(false) return d_error('You have set "false" in "if" condition');
define (www.php.net/define)('NODEBUG',1);
function d_error($error_text = 0)
{
        static (www.php.net/static) $errors = array (www.php.net/array)();
       
        if($error_text === NODEBUG && !function_exists (www.php.net/function_exists)('debug_backtrace')) $error_text = 0;
       
        if($error_text === 'all') return $errors;
        if($error_text === 0) return (sizeof (www.php.net/sizeof)($errors)>0 ? $errors[sizeof (www.php.net/sizeof)($errors)-1] : '');
        if($error_text === NODEBUG)
        {
                if(sizeof (www.php.net/sizeof)($errors)==0) return '';
                $p = explode (www.php.net/explode)(' ', $errors[sizeof (www.php.net/sizeof)($errors)-1],2);
                return $p[1];
        }
       
        if(function_exists (www.php.net/function_exists)('debug_backtrace'))
        {
                $tr = debug_backtrace (www.php.net/debug_backtrace)();
                $error_text = '['.$tr[1]['function'].'] '.$error_text;
        }
       
        $errors[]=$error_text;
        return false;
}
Функция возвращает булевый FALSE в случае ошибки. Узнать причину ошибки можно, вызвав d_error() без параметров, причём d_error() прилагается :).
Back to top
View user's profile Send private message Send e-mail
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Sun Dec 09, 2007 11:20 pm (спустя 35 минут; написано за 1 минуту 37 секунд)
   Post subject:
Reply with quote

К вопросу о том, зачем такая функция нужна, отвечу: очень приятно, когда все папки открываются без задержек, даже если количество файлов в папке огромно и достигает нескольких тысяч (большинство файловых менеджеров, даже не web-based, начинают ощутимо тормозить на таких объёмах).
Back to top
View user's profile Send private message Send e-mail
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Wed Dec 12, 2007 2:08 pm (спустя 2 дня 14 часов 48 минут; написано за 1 минуту 25 секунд)
   Post subject:
Reply with quote

Интересно, неужели я сам все эти 15000 просмотров набил :)? Господа, скажите, хоть кто-нибудь из этих 15000 просмотревших обратил внимание на семество функций advanced_copy_*() и на новую d_filelist_extreme()?
Back to top
View user's profile Send private message Send e-mail
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Thu Dec 13, 2007 9:01 pm (спустя 1 день 6 часов 52 минуты; написано за 11 минут 49 секунд)
   Post subject:
Reply with quote

Используем возможности PHP и JavaScript ещё более полно:

Семейство функций multipart_*() -- продолжение идей, которые были заложены в функции advanced_copy_*() -- копированию файлов в несколько приёмов.

Функции multipart_*() позволяют делать вообще любые операции с файлами, которые Вам нужны, в несколько приёмов с сохранением промежуточного состояния. Это может понадобиться, если вы хотите посчитать объём какой-нибудь огромной папки, скопировать большой массив файлов, или даже удалить большую папку. Юзвери -- существа нетерпеливые, поэтому если состояние операции не будет показываться, то они вряд ли будут от этого сильно счастливы.

Код функций (с описанием):
Code (php): скопировать код в буфер обмена
<?
define (www.php.net/define)('MAX_MULTIPART_TIME', 4); /* how many seconds can operations be run */

function have_time()
{
        static (www.php.net/static) $start = false;
        if($start === false) $start = time (www.php.net/time)();
       
        return (time (www.php.net/time)()-$start) < MAX_MULTIPART_TIME;
}

/*
 * function, that begins multipart operation
 *
 * PARAMS: array $params
 *
 * array $params -- see possible keys in the beginning of function
 *
 * RETURN:
 *
 * array $cache -- an array (you should not know it's structure) with data
 *                 for multipart_cont()
 */


function multipart_begin($params)
{
        $files = array (www.php.net/array)(); // initial array of files & folders to process
        $data  = array (www.php.net/array)(); // any information your functions may need to run
        $basedir = isset (www.php.net/isset)($_SESSION['DIR']) ? $_SESSION['DIR'] : getcwd (www.php.net/getcwd)();
       
        /* $processors is array of function names to process file
         * ($filename -- name of file or directory):

                begin($filename, $data)

                  'begin' is name of function to start processing file.
                  function must return FALSE on failure and $resumedata array for cont() or
                  TRUE if you will not use cont(), with cont() being a continue function
                  described below.

           the next two are not obligatory:

                cont($filename, $data, $resumedata):
               
                  function that continues the processing (should not work too long),
                  it should return TRUE on successfull finish, FALSE on error and
                  $resumedata array for temporary information, which is saved between
                  multipart_cont() calls. If function does not need resume data, please
                  return empty array instead of something else (because of strict
                  comparison with bool TRUE and FALSE in multipart_cont() ).

                stop($filename, $data, $successful):

                  function to be executed on successful (or not) end of operation
        */


        $processors = array (www.php.net/array)('begin','cont','stop');
       
        /*
       
        $dircall:
         when to call processor for directory? before calling
         file processors ('before'), after calling on all files in dir ('after')
       
         HINT: 'before' is for copying, 'after' -- for deleting items

        */

       
        $dircall = 'before';
       
        extract (www.php.net/extract)($params, EXTR_OVERWRITE);
       
        /* "mark" all files as being of unknown type (see multipart_cont()) */
        foreach($files as $k=>$v) $files[$k] = 'n'.$v;
       
        if(sizeof (www.php.net/sizeof)($processors) == 1) $processors = array (www.php.net/array)($processors[0], false, false);
        else if(sizeof (www.php.net/sizeof)($processors) == 2) $processors = array (www.php.net/array)($processors[0], $processors[1], false);
        else if(sizeof (www.php.net/sizeof)($processors) != 3)
        {
                return d_error('Invalid processors: only from 1 to 3 processors supported');
        }
       
        return array (www.php.net/array)(
                'data' => $data,
                'basedir' => $basedir,
                'processors' => $processors,
                'dircall' => $dircall,
               
                'files' => $files, /* files left for processing */
               
                'curfile' => false, /* the name of processed file, if script was stopped at cont() function */
                'resume_data' => array (www.php.net/array)(),
        );
}

/*
 * function to continue the processing of files
 *
 * PARAMS: $cache -- obligatory parameter with function cache
 *
 * RETURN:
 *
 * TRUE on success (process finished successfully)
 * FALSE on error
 * array $cache if operation is to be continued
*/


function multipart_cont($cache)
{
        if(is_bool (www.php.net/is_bool)($cache)) return $cache; /* this line should be here */
       
        $keys = array_keys (www.php.net/array_keys)($cache);
       
        extract (www.php.net/extract)($cache);
        $cache = array (www.php.net/array)();
       
        list($b,$c,$s) = $processors;
       
        if($c == 'cont') $c = false;
        if($s == 'stop') $s = false;
       
        if($curfile) $files[] = 'i'.$curfile;
       
        /*
         * first symbol filename of $files will tell, what to do with file:
         *
         * i -- intermediate file, which needs continue processing (w/$resume_data)
         * n -- new file with unknown type: use all actions
         * d -- directory which should not be expanded, just execute processors
         *      (needed for $dircall = 'after' and 'before')
         */


        if(!@chdir (www.php.net/chdir)($basedir)) return d_error('cannot change directory to current');
       
        while($it = array_pop (www.php.net/array_pop)($files))
        {
                $a    = $it[0]; /* action */
                $name = substr (www.php.net/substr)($it, 1);
                $curfile = false;
               
                if(!have_time())
                {
                        $files[] = $it;
                       
                        foreach($keys as $key) $cache[$key] = $$key;
                        return $cache;
                }
               
                if(is_file (www.php.net/is_file)($name) || $a == 'd' || $a == 'i')/*only execute processors*/
                {
                        /* for intermediate files we already have $resume_data from cache */
                        /* TODO: do not just skip errors at begin function */
                        if($a != 'i' && ($resume_data=$b($name, $data)) === false) continue;
                       
                        if($c)
                        {
                                $have = true; /* for case when $resume_data = true */
                                $curfile = $name;
                               
                                while(is_array (www.php.net/is_array)($resume_data) && ($have=have_time()))
                                {
                                        $resume_data = $c($name, $data, $resume_data);
                                }
                               
                                if(!$have)
                                {
                                        foreach($keys as $key) $cache[$key] = $$key;
                                        return $cache;
                                }
                               
                                if($have && $s)
                                {
                                        $s($name, $data, $resume_data);
                                }
                        }
                }else if(is_dir (www.php.net/is_dir)($name))
                {
                        if(!@$dh = opendir (www.php.net/opendir)($name)) continue;
                       
                        if(/*$dircall == 'both' || */$dircall == 'after')  $files[] = 'd'.$name;
                       
                        /*
                         * we just get a list of files (even without determining type)
                         * because stat() (or is_file() or is_dir()) consumes much time.
                         * it is important if directory is huge (5000-50000 files)
                         */

                       
                        while(false!==($f=readdir (www.php.net/readdir)($dh)))
                        {
                                if($f=='.'||$f=='..') continue;
                                $files[] = 'n'.$name.'/'.$f;
                        }
                       
                        closedir (www.php.net/closedir)($dh);
                       
                        if(/*$dircall == 'both' || */$dircall == 'before') $files[] = 'd'.$name;
                }
        }
       
        return true;
}

// the function to log errors. If $error_text is set to 'all', the function returns an array of all error messages.
// If $error_text is not set, the function returns the last error message. if $error_text==NODEBUG, the name of function will be removed if it was present (in the beginning)
// Else it logs the error message and returns false.
//
// example of usage: if(false) return d_error('You have set "false" in "if" condition');
define (www.php.net/define)('NODEBUG',1);
function d_error($error_text = 0)
{
        static (www.php.net/static) $errors = array (www.php.net/array)();
       
        if($error_text === NODEBUG && !function_exists (www.php.net/function_exists)('debug_backtrace')) $error_text = 0;
       
        if($error_text === 'all') return $errors;
        if($error_text === 0) return (sizeof (www.php.net/sizeof)($errors)>0 ? $errors[sizeof (www.php.net/sizeof)($errors)-1] : '');
        if($error_text === NODEBUG)
        {
                if(sizeof (www.php.net/sizeof)($errors)==0) return '';
                $p = explode (www.php.net/explode)(' ', $errors[sizeof (www.php.net/sizeof)($errors)-1],2);
                return $p[1];
        }
       
        if(function_exists (www.php.net/function_exists)('debug_backtrace'))
        {
                $tr = debug_backtrace (www.php.net/debug_backtrace)();
                $error_text = '['.$tr[1]['function'].'] '.$error_text;
        }
       
        $errors[]=$error_text;
        return false;
}
?>
Простой пример использования -- подсчёт размера папки WINDOWS:
Code (php): скопировать код в буфер обмена
<?
include('multipart.php');

// simple multipart processor: size() -- puts information about size to $_SESSION

function size($name)
{
        $_SESSION['TOTAL_BYTES'] += filesize (www.php.net/filesize)($name);
       
        if(is_dir (www.php.net/is_dir)($name)) $_SESSION['DIRS']++;
        else              $_SESSION['FILES']++;
       
        return true;
}

session_start (www.php.net/session_start)();

if(isset (www.php.net/isset)($_GET['flush']))
{
        unset (www.php.net/unset)($_SESSION['cache']);
        $_SESSION['FILES'] = $_SESSION['DIRS'] = $_SESSION['TOTAL_BYTES'] = 0;
        header (www.php.net/header)('location: '.$_SERVER['PHP_SELF']);
        die (www.php.net/die)();
}

echo (www.php.net/echo) '<a href="?flush=all">flush all data</a><br>';


if(empty (www.php.net/empty)($_SESSION['cache']))
{
        $_SESSION['cache'] = multipart_begin(
       
        array (www.php.net/array)(
                'basedir'    => 'C:/',
                'files'      => array (www.php.net/array)('WINDOWS'),
                'processors' => array (www.php.net/array)('size'),
        )
       
        );
       
        if(!$_SESSION['cache']) die (www.php.net/die)(d_error());
       
        $_SESSION['TOTAL_BYTES'] = $_SESSION['DIRS'] = $_SESSION['FILES']0;
}

$_SESSION['cache'] = multipart_cont($_SESSION['cache']);

echo (www.php.net/echo) 'Size: '.$_SESSION['TOTAL_BYTES'].' bytes<br>Files: '.$_SESSION['FILES'].'<br>Folders: '.$_SESSION['DIRS'].'<br><br>';

if(!is_bool (www.php.net/is_bool)($_SESSION['cache']))
{
        echo (www.php.net/echo) '<a href="'.$_SERVER['PHP_SELF'].'">continue count</a>';
}else
{
        echo (www.php.net/echo) '<b>Count process finished</b>';
}
?>
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Goto page 1, 2  Next
Page 1 of 2    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML