Undoubtedly at some point when working with PHP you’ll wind up needing to access or manipulate the file system. PHP has plenty of file system related functions built right into the core for you to sink your teeth into, however you will often need to use a combination of them to carry out more slightly advanced tasks.
Here are a few functions I regularly use during my day to day meddling in PHP.
Delete a File/Recursively Delete a Directory
This function simply deletes a directory and all of its contents, it can also delete a single file.
Note: Be very careful with the path you pass to this!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
/** * Delete a file/recursively delete a directory * * NOTE: Be very careful with the path you pass to this! * * @param string $path The path to the file/directory to delete * @return void */ function delete_recursive($path) { if (is_dir($path)) { $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); foreach ($iterator as $file) { if ($file->isDir()) { rmdir($file->getPathname()); } else { unlink($file->getPathname()); } } rmdir($path); } else { unlink($path); } } |
Copy a File/Recursively Copy the Contents of a Directory
Have you ever needed to copy the contents of one directory to another? That’s exactly what the following function will do.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
/** * Copy a file or recursively copy a directories contents * * @param string $source The path to the source file/directory * @param string $dest The path to the destination directory * @return void */ function copy_recursive($source, $dest) { if (is_dir($source)) { $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST ); foreach ($iterator as $file) { if ($file->isDir()) { mkdir($dest.DIRECTORY_SEPARATOR.$iterator->getSubPathName()); } else { copy($file, $dest.DIRECTORY_SEPARATOR.$iterator->getSubPathName()); } } } else { copy($source, $dest); } } |
Get the Size of a File/Directory
Sometimes you need to calculate the size of a file or directory, PHP has filesize()
for files but lacks a function to do the same for directories. This function can do both!
Note: This function may return unexpected results for files larger than 2GB on 32bit hosts due to PHP’s integer type being 32bit signed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
/** * Return the size of a file or a directory and its contents in bytes * * NOTE: This function may return unexpected results for files larger than * 2GB on 32bit hosts due to PHP's integer type being 32bit signed. * * @param string $path The path to the file/directory to calculate the size of * @return int */ function size_recursive($path) { $size = 0; if (is_dir($path)) { $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); foreach ($iterator as $file) { $size += $file->getSize(); } } else { $size = filesize($path); } return $size; } |
Read the Last Few Lines of a File (aka tail for PHP)
I can recall a handful of times that I have had to read the last few lines of a large log file with PHP without loading the whole file into memory. Obviously I could just do tail -n <number of lines> <file>
on Unix-like systems, but what if your code is running on Windows?
That’s where this function jumps to the rescue.
NOTE: Only works with files that have CRLF, LF or CR newlines.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
/** * Read the last few lines of a file * * NOTE: Only works with files that have CRLF, LF or CR newlines * * @param string $file The path to the file to read from * @param int $lines The number of lines to return * @return string */ function tail($file, $lines) { if ($lines < 1) return ''; $line = ''; $line_count = 0; $prev_char = ''; $fp = fopen($file, 'r'); $cursor = -1; fseek($fp, $cursor, SEEK_END); $char = fgetc($fp); while ($char !== false) { if ($char === "\n" || $char === "\r") { fseek($fp, --$cursor, SEEK_END); $next_char = fgetc($fp); if ($char === "\n" && $next_char === "\r") { $line_count++; } elseif ($char === "\r" && $prev_char !== "\n") { $line_count++; } elseif ($char === "\n") { $line_count++; } fseek($fp, ++$cursor, SEEK_END); } if ($line_count == $lines) break; $line = $char.$line; $prev_char = $char; fseek($fp, --$cursor, SEEK_END); $char = fgetc($fp); } fclose($fp); return $line; } |
I hope you find these functions as useful as I do.