Related
what i am trying to do is to get directory of my page like this
Home / Clothes / Something
i have tried this but i didn't understand a lot in this but it doesn't work as i want it
<?php
// current directory
echo getcwd() . "\n";
chdir('cvs');
// current directory
echo getcwd() . "\n";
?>
here's example what i need to do
my page is example.com/clothes/something.php
and on that page "something.php" i want to echo out something like this
Home / clothes / Something
i forget what this was called but hope you understand
<?php
$path = $_SERVER["PHP_SELF"];
$parts = explode('/',$path);
if (count($parts) < 2)
{
echo("home");
}
else
{
echo ("Home » ");
for ($i = 1; $i < count($parts); $i++)
{
if (!strstr($parts[$i],"."))
{
echo("<a href=\"");
for ($j = 0; $j <= $i; $j++) {echo $parts[$j]."/";};
echo("\">". str_replace('-', ' ', $parts[$i])."</a> » ");
}
else
{
$str = $parts[$i];
$pos = strrpos($str,".");
$parts[$i] = substr($str, 0, $pos);
echo str_replace('-', ' ', $parts[$i]);
};
};
};
?>
Try something like this:
$subPath = '';
$path = explode('/', $_SERVER['REQUEST_URI']);
array_shift($path);
foreach ($path as $segment) {
$subPath.= $segment.'/';
echo "$segment / ";
}
You may need to tweak it a bit, but that's the basic idea.
[EDIT]
Or maybe something like this:
$Pages = [
'/clothes' => 'Clothes',
'/clothes/something.php' => 'Something'
];
$subPath = '';
$BreadCrumbs = [];
$path = explode('/', $_SERVER['REQUEST_URI']);
array_shift($path);
foreach ($path as $segment) {
$subPath.= '/'.$segment;
$BreadCrumbs[] = "$Pages[$subPath]";
}
echo implode(' > ', $BreadCrumbs);
If your version of PHP is before 5.4.0, then you'll need a different syntax for the arrays:
$Pages = array(
'/clothes' => 'Clothes',
'/clothes/something.php' => 'Something'
);
$BreadCrumbs = array();
[EDIT]
OK, one last go:
<?php
$Pages = array(
'clothes' => 'Clothes',
'something' => 'Something'
);
$path = $_SERVER["PHP_SELF"];
$parts = explode('/',$path);
if (count($parts) < 2)
{
echo("home");
}
else
{
echo ("Home » ");
for ($i = 1; $i < count($parts); $i++)
{
if (!strstr($parts[$i],"."))
{
echo("<a href=\"");
for ($j = 0; $j <= $i; $j++) {echo $parts[$j]."/";};
echo("\">". str_replace('-', ' ', $Pages[$parts[$i]])."</a> » ");
}
else
{
$str = $parts[$i];
$pos = strrpos($str,".");
$parts[$i] = substr($str, 0, $pos);
echo str_replace('-', ' ', $Pages[$parts[$i]]);
};
};
};
?>
I found a script which can extract the artist & title name from an Icecast or Shoutcast stream.
I want the script to update automatically when a song changed, at the moment its working only when i execute it. I'm new to PHP so any help will be appreciated.
Thanks!
define('CRLF', "\r\n");
class streaminfo{
public $valid = false;
public $useragent = 'Winamp 2.81';
protected $headers = array();
protected $metadata = array();
public function __construct($location){
$errno = $errstr = '';
$t = parse_url($location);
$sock = fsockopen($t['host'], $t['port'], $errno, $errstr, 5);
$path = isset($t['path'])?$t['path']:'/';
if ($sock){
$request = 'GET '.$path.' HTTP/1.0' . CRLF .
'Host: ' . $t['host'] . CRLF .
'Connection: Close' . CRLF .
'User-Agent: ' . $this->useragent . CRLF .
'Accept: */*' . CRLF .
'icy-metadata: 1'.CRLF.
'icy-prebuffer: 65536'.CRLF.
(isset($t['user'])?'Authorization: Basic '.base64_encode($t['user'].':'.$t['pass']).CRLF:'').
'X-TipOfTheDay: Winamp "Classic" rulez all of them.' . CRLF . CRLF;
if (fwrite($sock, $request)){
$theaders = $line = '';
while (!feof($sock)){
$line = fgets($sock, 4096);
if('' == trim($line)){
break;
}
$theaders .= $line;
}
$theaders = explode(CRLF, $theaders);
foreach ($theaders as $header){
$t = explode(':', $header);
if (isset($t[0]) && trim($t[0]) != ''){
$name = preg_replace('/[^a-z][^a-z0-9]*/i','', strtolower(trim($t[0])));
array_shift($t);
$value = trim(implode(':', $t));
if ($value != ''){
if (is_numeric($value)){
$this->headers[$name] = (int)$value;
}else{
$this->headers[$name] = $value;
}
}
}
}
if (!isset($this->headers['icymetaint'])){
$data = ''; $metainterval = 512;
while(!feof($sock)){
$data .= fgetc($sock);
if (strlen($data) >= $metainterval) break;
}
$this->print_data($data);
$matches = array();
preg_match_all('/([\x00-\xff]{2})\x0\x0([a-z]+)=/i', $data, $matches, PREG_OFFSET_CAPTURE);
preg_match_all('/([a-z]+)=([a-z0-9\(\)\[\]., ]+)/i', $data, $matches, PREG_SPLIT_NO_EMPTY);
echo '<pre>';var_dump($matches);echo '</pre>';
$title = $artist = '';
foreach ($matches[0] as $nr => $values){
$offset = $values[1];
$length = ord($values[0]{0}) +
(ord($values[0]{1}) * 256)+
(ord($values[0]{2}) * 256*256)+
(ord($values[0]{3}) * 256*256*256);
$info = substr($data, $offset + 4, $length);
$seperator = strpos($info, '=');
$this->metadata[substr($info, 0, $seperator)] = substr($info, $seperator + 1);
if (substr($info, 0, $seperator) == 'title') $title = substr($info, $seperator + 1);
if (substr($info, 0, $seperator) == 'artist') $artist = substr($info, $seperator + 1);
}
$this->metadata['streamtitle'] = $artist . ' - ' . $title;
}else{
$metainterval = $this->headers['icymetaint'];
$intervals = 0;
$metadata = '';
while(1){
$data = '';
while(!feof($sock)){
$data .= fgetc($sock);
if (strlen($data) >= $metainterval) break;
}
//$this->print_data($data);
$len = join(unpack('c', fgetc($sock))) * 16;
if ($len > 0){
$metadata = str_replace("\0", '', fread($sock, $len));
break;
}else{
$intervals++;
if ($intervals > 100) break;
}
}
$metarr = explode(';', $metadata);
foreach ($metarr as $meta){
$t = explode('=', $meta);
if (isset($t[0]) && trim($t[0]) != ''){
$name = preg_replace('/[^a-z][^a-z0-9]*/i','', strtolower(trim($t[0])));
array_shift($t);
$value = trim(implode('=', $t));
if (substr($value, 0, 1) == '"' || substr($value, 0, 1) == "'"){
$value = substr($value, 1);
}
if (substr($value, -1) == '"' || substr($value, -1) == "'"){
$value = substr($value, 0, -1);
}
if ($value != ''){
$this->metadata[$name] = $value;
}
}
}
}
fclose($sock);
$this->valid = true;
}else echo 'unable to write.';
}else echo 'no socket '.$errno.' - '.$errstr.'.';
}
public function print_data($data){
$data = str_split($data);
$c = 0;
$string = '';
echo "<pre>\n000000 ";
foreach ($data as $char){
$string .= addcslashes($char, "\n\r\0\t");
$hex = dechex(join(unpack('C', $char)));
if ($c % 4 == 0) echo ' ';
if ($c % (4*4) == 0 && $c != 0){
foreach (str_split($string) as $s){
//echo " $string\n";
if (ord($s) < 32 || ord($s) > 126){
echo '\\'.ord($s);
}else{
echo $s;
}
}
echo "\n";
$string = '';
echo str_pad($c, 6, '0', STR_PAD_LEFT).' ';
}
if (strlen($hex) < 1) $hex = '00';
if (strlen($hex) < 2) $hex = '0'.$hex;
echo $hex.' ';
$c++;
}
echo " $string\n</pre>";
}
public function __get($name){
if (isset($this->metadata[$name])){
return $this->metadata[$name];
}
if (isset($this->headers[$name])){
return $this->headers[$name];
}
return null;
}
}
$t = new streaminfo('http://64.236.34.196:80/stream/1014'); // get metadata
echo Meta Interval: $t->icymetaint;
echo Current Track: $t->streamtitle;
You will need to constantly query the stream at a set interval to find when the song changes.
This can be best done by scheduling a cron job.
If on Windows, you should use the Windows Task Scheduler
If you want to run the PHP script to keep your meta data up to date (I'm assuming you're making a website and using html audio tags here) you can use the ontimeupdate event with an ajax function. If you're not you probably should look up your audio playback documentation for something similar.
<audio src="http://ip:port/;" ontimeupdate="loadXMLDoc()">
You can find a great example here http://www.w3schools.com/php/php_ajax_php.asp
You want to use the PHP echo function all the relevant information at once using one php variable at the very end of your script.
<?php ....
$phpVar=$streamtitle;
$phpVar2=$streamsong;
$result="I want my string to look like this: <br> {$phpVar} {$phpVar2}";
echo $result;
?>
and then use the function called by the .onreadystatechange to modify the particular elements you want on your website by using the .resonseText (this will contain the same content as your PHP script's echo).
After SCOURING the web for 4 hours, this is the only Shoutcast metadata script I've found that works! Thankyou.
To run this constantly, why not use a setInterval combined with jQuery's AJAX call?
<script>
$(function() {
setInterval(getTrackName,16000);
});
function getTrackName() {
$.ajax({
url: "track_name.php"
})
.done(function( data ) {
$( "#results" ).text( data );
});
}
</script>
Also your last couple 'echo' lines were breaking the script for me. Just put quotes around the Meta Interval, etc....
I have this function that checks for a filename. If it exists, it increments it by one following this patter:
image.jpg
image1.jpg
image2.jpg
The problem comes on the 4th image, it comes back with 0.jpg.
Here is the relevant code:
...
$filetarget = $this->make_image_filename($directory, $new_filename, $extension);
if(!move_uploaded_file($file['tmp_name'], $filetarget)){
$error[$index] = 'copy';
}
...
private function make_image_filename($directory, $name = '', $extension){
if(empty($name)) $name = 'NULL';
$filetarget = $directory.$name.$extension;
if(file_exists($filetarget)){
$name = $this->increment_filename($name);
return $this->make_image_filename($directory, $name, $extension);
} else {
return $filetarget;
}
}
private function increment_filename($name){
$index = $this->get_filename_index($name);
if(is_numeric($index)){
$pos = strpos($name, $index);
$name = substr($name, 0, $pos);
}
if(is_null($index)){
$index = 0;
}
++$index;
return $name.$index;
}
private function get_filename_index($name){
// CHECK FOR INDEX
$i = 1;
$index = substr($name, -$i);
$last_chars = substr($name, -$i);
while(is_numeric($last_chars)){
++$i;
$last_chars = substr($name, -$i);
if(is_numeric($last_chars)){
$index = $last_chars;
}
}
if(is_numeric($index)){
return $index;
} else {
return NULL;
}
}
I am in the process now of isolating this code on my local server to run some tests. Can you see anything inherently flawed in this process?
Here is a function I use to do the same thing:
function make_unique($full_path) {
$file_name = basename($full_path);
$directory = dirname($full_path).DIRECTORY_SEPARATOR;
$i = 2;
while (file_exists($directory.$file_name)) {
$parts = explode('.', $file_name);
// Remove any numbers in brackets in the file name
$parts[0] = preg_replace('/\(([0-9]*)\)$/', '', $parts[0]);
$parts[0] .= '('.$i.')';
$new_file_name = implode('.', $parts);
if (!file_exists($new_file_name)) {
$file_name = $new_file_name;
}
$i++;
}
return $directory.$file_name;
}
(except it make file names like image(1).jpg image(2).jpg)
How about this:
function get_next_file_name($file) {
if (!preg_match('/^(\D+)(\d*)(\.\S+)$/', $file, $match)) {
throw new Exception('bad file name format');
}
return $match[1] . (empty($match[2]) ? 1 : ($match[2] + 1)) . $match[3];
}
echo get_next_file_name('image.jpg'), "\n"; // prints image1.jpg
echo get_next_file_name('image1.jpg'), "\n"; // prints image2.jpg
echo get_next_file_name('image999.jpg'), "\n"; // prints image1000.jpg
This question comes from this How to proportionally size images to fit dimensions of 200px x 150px thumbnail in css?, but since I feel it`s not a CSS related question anymore I thought I would create a new question. I am trying to proportionally fit images into thumbnails here http://giantmango.com/contest. I tried setting the css img tag to the below, but all images have the size of 200px x 200px. There is not another css line that has 200px as a height. I am suspecting it is something else.
img {
max-height: 150px;
max-width: 200px;
}
This function is called to return the images and thinking it might be this.
<?php
$content = get_the_content('Concept');
$content = apply_filters('the_content', $content);
list($col_class, $grid_img) = adjust_grid_image(
$content,
$col_w,
$gap_w,
$max_col,
$flg_img_forcelink,
$flg_obj_fit
);
?>
<div <?php post_class('grid-item ' . $col_class); ?> id="post-<?php the_ID(); ?>">
<?php if ($grid_img) echo '<div class="grid-image">' . $grid_img . '</div>'; ?>
These are the parameters that I have it set to.
$col_w = 200; // width of grid column
$gap_w = 7; // padding + margin-right (15+15+5)
$max_col = 5; // max column size (style div.x1 ~ xN)
$flg_img_forcelink = true; // add/overwrite a link which links to a single post (permalink).
$flg_img_extract = true; // in single post page, extract thumbnail link to an original image.
$flg_obj_fit = 'large-fit'; // none | small-fit | large-fit ... how to fit size of object tag.
This is the functions.php file that runs adjust_grid_image, but I am unsure of what it is doing. Is this setting my images to 200px x 200px? If so, what parameter must I change in order for it to not hardcode 200px as the height of images so I can set it in the css?
/*
* return class name and image tag (resized w/h attributes) to fit a grid.
*/
function adjust_grid_image($content, $col_w, $gap_w, $max_col, $flg_img_forcelink, $flg_obj_fit) {
global $post;
$col_class_base = 'x';
$col_class = $col_class_base . '1'; // default column-width class
$arr_w = array();
for ($i=0; $i<$max_col; $i++) {
$arr_w[] = ($col_w * ($i+1)) + ($gap_w * $i);
}
$grid_img = '';
$w = $h = 0;
$matches1 = $matches2 = $matches3 = array();
// search *first* img/object tag
preg_match('/<(img|object)(?:[^>]+?)>/', $content, $matches1);
if ($matches1[1] == 'img') {
preg_match('/<img(?:.+?)src="(.+?)"(?:[^>]+?)>/', $content, $matches2);
$img_url = ($matches2[1]) ? $matches2[1] : '';
if ($img_url) {
// first, try to get attributes
$matches_w = $matches_h = array();
preg_match('/width="([0-9]+)"/', $matches2[0], $matches_w);
preg_match('/height="([0-9]+)"/', $matches2[0], $matches_h);
if ($matches_w[1] and $matches_h[1]) {
$w = $matches_w[1];
$h = $matches_h[1];
}
else {
// ... or get original size info.
$upload_path = trim( get_option('upload_path') );
$mark = substr(strrchr($upload_path, "/"), 1); // default mark is 'uploads'
preg_match("#$mark(/.+)$#", $img_url, $split_url);
// split($mark, $img_url)
if ($split_url[1] != null) {
$img_path = $upload_path . $split_url[1];
list($w, $h) = #getimagesize($img_path);
}
}
}
for ($i=0; $i<$max_col; $i++) { // set new width and col_class
if ( ($i >= $max_col - 1) or ($w < $arr_w[$i+1]) ) {
$nw = $arr_w[$i];
$col_class = $col_class_base . ($i+1);
break;
}
}
$nh = (!$w or !$h) ? $nw : intval( ($h * $nw) / $w ); // set new height
$grid_img = $matches2[0];
// add width/height properties if nothing
$flg_no_w = (strpos($grid_img_edit, 'width=') === false);
$flg_no_h = (strpos($grid_img_edit, 'height=') === false);
if ($flg_no_w or $flg_no_h) {
$grid_img_close = (substr($grid_img, -2) == '/>') ? '/>' : '>';
$grid_img_edit = substr( $grid_img, 0, -(strlen($grid_img_close)) );
$grid_img_edit .= ($flg_no_w) ? ' width="0"' : '';
$grid_img_edit .= ($flg_no_h) ? ' height="0"' : '';
$grid_img = $grid_img_edit . $grid_img_close;
}
// replace new width/height properties
$grid_img = preg_replace('/width="(\d+)"/', 'width="'. $nw .'"', $grid_img);
$grid_img = preg_replace('/height="(\d+)"/', 'height="'. $nh .'"', $grid_img);
// check image link
//$chk_imglink = '/(<a(?:.+?)rel="(?:lightbox[^"]*?)"(?:[^>]*?)>)'. preg_quote($matches2[0], '/') .'/';
$chk_imglink = '/(<a(?:.+?)href="(?:.+?\.(?:jpe?g|png|gif))"(?:[^>]*?)>)'. preg_quote($matches2[0], '/') .'/';
if ($flg_img_forcelink) {
$grid_img = '' . $grid_img . '';
}
else if ( preg_match($chk_imglink, $content, $matches3) ) {
$grid_img = $matches3[1] . $grid_img . '</a>';
}
}
else if ($matches1[1] == 'object') {
preg_match('/<object(.+?)<\/object>/', $content, $matches2);
$matches_w = $matches_h = array();
preg_match('/width="([0-9]+)"/', $matches2[0], $matches_w);
preg_match('/height="([0-9]+)"/', $matches2[0], $matches_h);
if ($matches_w[1] and $matches_h[1]) {
$w = $matches_w[1];
$h = $matches_h[1];
}
else {
$flg_obj_fit = 'none';
}
//set col_class (and new width if in '*-fit' condition)
if ($flg_obj_fit == 'small-fit') {
for ($i=0; $i<$max_col; $i++) {
if ($i >= $max_col -1) {
$nw = $arr_w[$i];
$col_class = $col_class_base . ($i+1);
break;
}
else if ( $w < $arr_w[$i+1] ) {
$nw = $arr_w[$i];
$col_class = $col_class_base . ($i+1);
break;
}
}
}
else if ($flg_obj_fit == 'large-fit') {
for ($i=$max_col -1; $i>=0; $i--) {
if ( $w > $arr_w[$i] ) {
if ($i >= $max_col -1) {
$nw = $arr_w[$i];
$col_class = $col_class_base . ($i+1);
}
else {
$nw = $arr_w[$i+1];
$col_class = $col_class_base . ($i+2);
}
break;
}
if ($i == 0) {
$nw = $arr_w[$i];
$col_class = $col_class_base . ($i+1);
}
}
}
else {
for ($i=0; $i<$max_col; $i++) {
if ($i >= $max_col -1) {
$col_class = $col_class_base . ($i+1);
break;
}
else if ( $w < $arr_w[$i] ) {
$col_class = $col_class_base . ($i+1);
break;
}
}
}
$nh = (!$w or !$h) ? $nw : intval( ($h * $nw) / $w ); // set new height
$grid_img = $matches2[0];
if ($flg_obj_fit == 'small-fit' or $flg_obj_fit == 'large-fit') {
// replace new width/height properties
$grid_img = preg_replace('/width="(\d+)"/', 'width="'. $nw .'"', $grid_img);
$grid_img = preg_replace('/height="(\d+)"/', 'height="'. $nh .'"', $grid_img);
}
}
return array($col_class, $grid_img);
}
Thank you for looking at all of this.
This is some intermediate function. There will be probably some other part in the code which uses the return value from this function and actually outputs HTML. You should locate this part and comment the piece which output the width and height settings.
Pay attention, though, that if your images have variable proportions and you rescale them mantaining these proportions (via CSS), they will not fit in a grid anymore. They will look more scattered on the page than they are now.
EDIT Now that you have added more details, I think it should be enough to remove the section starting with the comment // add width/height properties if nothing
function foldersize($path) {
$total_size = 0;
$files = scandir($path);
foreach($files as $t) {
if (is_dir(rtrim($path, '/') . '/' . $t)) {
if ($t<>"." && $t<>"..") {
$size = foldersize(rtrim($path, '/') . '/' . $t);
$total_size += $size;
}
} else {
$size = filesize(rtrim($path, '/') . '/' . $t);
$total_size += $size;
}
}
return $total_size;
}
function format_size($size) {
$mod = 1024;
$units = explode(' ','B KB MB GB TB PB');
for ($i = 0; $size > $mod; $i++) {
$size /= $mod;
}
return round($size, 2) . ' ' . $units[$i];
}
$SIZE_LIMIT = 5368709120; // 5 GB
$sql="select * from users order by id";
$result=mysql_query($sql);
while($row=mysql_fetch_array($result)) {
$disk_used = foldersize("C:/xampp/htdocs/freehosting/".$row['name']);
$disk_remaining = $SIZE_LIMIT - $disk_used;
print 'Name: ' . $row['name'] . '<br>';
print 'diskspace used: ' . format_size($disk_used) . '<br>';
print 'diskspace left: ' . format_size($disk_remaining) . '<br><hr>';
}
php disk_total_space
Any idea why the processor usage shoot up too high or 100% till the script execution is finish ? Can anything be done to optimize it? or is there any other alternative way to check folder and folders inside it size?
function GetDirectorySize($path){
$bytestotal = 0;
$path = realpath($path);
if($path!==false && $path!='' && file_exists($path)){
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)) as $object){
$bytestotal += $object->getSize();
}
}
return $bytestotal;
}
The same idea as Janith Chinthana suggested.
With a few fixes:
Converts $path to realpath
Performs iteration only if path is valid and folder exists
Skips . and .. files
Optimized for performance
The following are other solutions offered elsewhere:
If on a Windows Host:
<?
$f = 'f:/www/docs';
$obj = new COM ( 'scripting.filesystemobject' );
if ( is_object ( $obj ) )
{
$ref = $obj->getfolder ( $f );
echo 'Directory: ' . $f . ' => Size: ' . $ref->size;
$obj = null;
}
else
{
echo 'can not create object';
}
?>
Else, if on a Linux Host:
<?
$f = './path/directory';
$io = popen ( '/usr/bin/du -sk ' . $f, 'r' );
$size = fgets ( $io, 4096);
$size = substr ( $size, 0, strpos ( $size, "\t" ) );
pclose ( $io );
echo 'Directory: ' . $f . ' => Size: ' . $size;
?>
directory size using php filesize and RecursiveIteratorIterator.
This works with any platform which is having php 5 or higher version.
/**
* Get the directory size
* #param string $directory
* #return integer
*/
function dirSize($directory) {
$size = 0;
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)) as $file){
$size+=$file->getSize();
}
return $size;
}
A pure php example.
<?php
$units = explode(' ', 'B KB MB GB TB PB');
$SIZE_LIMIT = 5368709120; // 5 GB
$disk_used = foldersize("/webData/users/vdbuilder#yahoo.com");
$disk_remaining = $SIZE_LIMIT - $disk_used;
echo("<html><body>");
echo('diskspace used: ' . format_size($disk_used) . '<br>');
echo( 'diskspace left: ' . format_size($disk_remaining) . '<br><hr>');
echo("</body></html>");
function foldersize($path) {
$total_size = 0;
$files = scandir($path);
$cleanPath = rtrim($path, '/'). '/';
foreach($files as $t) {
if ($t<>"." && $t<>"..") {
$currentFile = $cleanPath . $t;
if (is_dir($currentFile)) {
$size = foldersize($currentFile);
$total_size += $size;
}
else {
$size = filesize($currentFile);
$total_size += $size;
}
}
}
return $total_size;
}
function format_size($size) {
global $units;
$mod = 1024;
for ($i = 0; $size > $mod; $i++) {
$size /= $mod;
}
$endIndex = strpos($size, ".")+3;
return substr( $size, 0, $endIndex).' '.$units[$i];
}
?>
function get_dir_size($directory){
$size = 0;
$files = glob($directory.'/*');
foreach($files as $path){
is_file($path) && $size += filesize($path);
is_dir($path) && $size += get_dir_size($path);
}
return $size;
}
Thanks to Jonathan Sampson, Adam Pierce and Janith Chinthana I did this one checking for most performant way to get the directory size. Should work on Windows and Linux Hosts.
static function getTotalSize($dir)
{
$dir = rtrim(str_replace('\\', '/', $dir), '/');
if (is_dir($dir) === true) {
$totalSize = 0;
$os = strtoupper(substr(PHP_OS, 0, 3));
// If on a Unix Host (Linux, Mac OS)
if ($os !== 'WIN') {
$io = popen('/usr/bin/du -sb ' . $dir, 'r');
if ($io !== false) {
$totalSize = intval(fgets($io, 80));
pclose($io);
return $totalSize;
}
}
// If on a Windows Host (WIN32, WINNT, Windows)
if ($os === 'WIN' && extension_loaded('com_dotnet')) {
$obj = new \COM('scripting.filesystemobject');
if (is_object($obj)) {
$ref = $obj->getfolder($dir);
$totalSize = $ref->size;
$obj = null;
return $totalSize;
}
}
// If System calls did't work, use slower PHP 5
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir));
foreach ($files as $file) {
$totalSize += $file->getSize();
}
return $totalSize;
} else if (is_file($dir) === true) {
return filesize($dir);
}
}
Even though there are already many many answers to this post, I feel I have to add another option for unix hosts that only returns the sum of all file sizes in the directory (recursively).
If you look at Jonathan's answer he uses the du command. This command will return the total directory size but the pure PHP solutions posted by others here will return the sum of all file sizes. Big difference!
What to look out for
When running du on a newly created directory, it may return 4K instead of 0. This may even get more confusing after having deleted files from the directory in question, having du reporting a total directory size that does not correspond to the sum of the sizes of the files within it. Why? The command du returns a report based on some file settings, as Hermann Ingjaldsson commented on this post.
The solution
To form a solution that behaves like some of the PHP-only scripts posted here, you can use ls command and pipe it to awk like this:
ls -ltrR /path/to/dir |awk '{print \$5}'|awk 'BEGIN{sum=0} {sum=sum+\$1} END {print sum}'
As a PHP function you could use something like this:
function getDirectorySize( $path )
{
if( !is_dir( $path ) ) {
return 0;
}
$path = strval( $path );
$io = popen( "ls -ltrR {$path} |awk '{print \$5}'|awk 'BEGIN{sum=0} {sum=sum+\$1} END {print sum}'", 'r' );
$size = intval( fgets( $io, 80 ) );
pclose( $io );
return $size;
}
I found this approach to be shorter and more compatible. The Mac OS X version of "du" doesn't support the -b (or --bytes) option for some reason, so this sticks to the more-compatible -k option.
$file_directory = './directory/path';
$output = exec('du -sk ' . $file_directory);
$filesize = trim(str_replace($file_directory, '', $output)) * 1024;
Returns the $filesize in bytes.
Johnathan Sampson's Linux example didn't work so good for me. Here's an improved version:
function getDirSize($path)
{
$io = popen('/usr/bin/du -sb '.$path, 'r');
$size = intval(fgets($io,80));
pclose($io);
return $size;
}
It works perfectly fine .
public static function folderSize($dir)
{
$size = 0;
foreach (glob(rtrim($dir, '/') . '/*', GLOB_NOSORT) as $each) {
$func_name = __FUNCTION__;
$size += is_file($each) ? filesize($each) : static::$func_name($each);
}
return $size;
}
There are several things you could do to optimise the script - but maximum success would make it IO-bound rather than CPU-bound:
Calculate rtrim($path, '/') outside the loop.
make if ($t<>"." && $t<>"..") the outer test - it doesn't need to stat the path
Calculate rtrim($path, '/') . '/' . $t once per loop - inside 2) and taking 1) into account.
Calculate explode(' ','B KB MB GB TB PB'); once rather than each call?
PHP get directory size (with FTP access)
After hard work, this code works great!!!! and I want to share with the community (by MundialSYS)
function dirFTPSize($ftpStream, $dir) {
$size = 0;
$files = ftp_nlist($ftpStream, $dir);
foreach ($files as $remoteFile) {
if(preg_match('/.*\/\.\.$/', $remoteFile) || preg_match('/.*\/\.$/', $remoteFile)){
continue;
}
$sizeTemp = ftp_size($ftpStream, $remoteFile);
if ($sizeTemp > 0) {
$size += $sizeTemp;
}elseif($sizeTemp == -1){//directorio
$size += dirFTPSize($ftpStream, $remoteFile);
}
}
return $size;
}
$hostname = '127.0.0.1'; // or 'ftp.domain.com'
$username = 'username';
$password = 'password';
$startdir = '/public_html'; // absolute path
$files = array();
$ftpStream = ftp_connect($hostname);
$login = ftp_login($ftpStream, $username, $password);
if (!$ftpStream) {
echo 'Wrong server!';
exit;
} else if (!$login) {
echo 'Wrong username/password!';
exit;
} else {
$size = dirFTPSize($ftpStream, $startdir);
}
echo number_format(($size / 1024 / 1024), 2, '.', '') . ' MB';
ftp_close($ftpStream);
Good code!
Fernando
Object Oriented Approach :
/**
* Returns a directory size
*
* #param string $directory
*
* #return int $size directory size in bytes
*
*/
function dir_size($directory)
{
$size = 0;
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory)) as $file)
{
$size += $file->getSize();
}
return $size;
}
Fast and Furious Approach :
function dir_size2($dir)
{
$line = exec('du -sh ' . $dir);
$line = trim(str_replace($dir, '', $line));
return $line;
}
Code adjusted to access main directory and all sub folders within it. This would return the full directory size.
function get_dir_size($directory){
$size = 0;
$files= glob($directory.'/*');
foreach($files as $path){
is_file($path) && $size += filesize($path);
if (is_dir($path))
{
$size += get_dir_size($path);
}
}
return $size;
}
if you are hosted on Linux:
passthru('du -h -s ' . $DIRECTORY_PATH)
It's better than foreach
Regarding Johnathan Sampson's Linux example, watch out when you are doing an intval on the outcome of the "du" function, if the size is >2GB, it will keep showing 2GB.
Replace:
$totalSize = intval(fgets($io, 80));
by:
strtok(fgets($io, 80), " ");
supposed your "du" function returns the size separated with space followed by the directory/file name.
Just another function using native php functions.
function dirSize($dir)
{
$dirSize = 0;
if(!is_dir($dir)){return false;};
$files = scandir($dir);if(!$files){return false;}
$files = array_diff($files, array('.','..'));
foreach ($files as $file) {
if(is_dir("$dir/$file")){
$dirSize += dirSize("$dir/$file");
}else{
$dirSize += filesize("$dir/$file");
}
}
return $dirSize;
}
NOTE: this function returns the files sizes, NOT the size on disk
Evolved from Nate Haugs answer I created a short function for my project:
function uf_getDirSize($dir, $unit = 'm')
{
$dir = trim($dir, '/');
if (!is_dir($dir)) {
trigger_error("{$dir} not a folder/dir/path.", E_USER_WARNING);
return false;
}
if (!function_exists('exec')) {
trigger_error('The function exec() is not available.', E_USER_WARNING);
return false;
}
$output = exec('du -sb ' . $dir);
$filesize = (int) trim(str_replace($dir, '', $output));
switch ($unit) {
case 'g': $filesize = number_format($filesize / 1073741824, 3); break; // giga
case 'm': $filesize = number_format($filesize / 1048576, 1); break; // mega
case 'k': $filesize = number_format($filesize / 1024, 0); break; // kilo
case 'b': $filesize = number_format($filesize, 0); break; // byte
}
return ($filesize + 0);
}
A one-liner solution. Result in bytes.
$size=array_sum(array_map('filesize', glob("{$dir}/*.*")));
Added bonus: you can simply change the file mask to whatever you like, and count only certain files (eg by extension).
This is the simplest possible algorithm to find out directory size irrespective of the programming language you are using.
For PHP specific implementation. go to: Calculate Directory Size in PHP | Explained with Algorithm | Working Code