<!DOCTYPE html>
<!-- ========================================== kroc camen of camen design ============================================= -->
<title>code · Sorting a Directory Listing Folders First, Then by File Type, Then by Name in PHP</title>
<link rel="stylesheet" type="text/css" href="/design/design.css" />
<meta name="viewport" content="width=device-width, maximum-scale=1.0, user-scalable=no" />
<link rel="alternate" type="application/rss+xml" href="/code/rss" title="Just code" />
<link rel="canonical" href="/code/php_directory_sorting" />
<!-- =================================================================================================================== -->
<header>
<h1><a href="/" rel="index">
Camen Design
</a></h1>
<nav><ul>
<li><a href="/">all</a></li>
<li><a href="/projects">projects</a></li>
<li><a href="http://forum.camendesign.com">forum</a></li>
</ul><ul>
<li><a href="/quote/">quote</a></li>
<li><a href="/blog/">blog</a></li>
<li><a href="/photo/">photo</a></li>
<li><a href="/writing/">writing</a></li>
<li><a href="/code/" rel="tag">code</a></li>
<li><a href="/art/">art</a></li>
<li><a href="/link/">link</a></li>
<li><a href="/poem/">poem</a></li>
<li><a href="/audio/">audio</a></li>
</ul><ul>
<li><a href="/web-dev/">web-dev</a></li>
<li><a href="/annoyances/">annoyances</a></li>
<li><a href="/code-is-art/">code-is-art</a></li>
<li><a href="/inspiration/">inspiration</a></li>
<li><a href="/windows/">windows</a></li>
<li><a href="/gaming/">gaming</a></li>
<li><a href="/mac/">mac</a></li>
<li><a href="/gift/">gift</a></li>
<li><a href="/osnews/">osnews</a></li>
<li><a href="/c64/">c64</a></li>
<li><a href="/linux/">linux</a></li>
</ul>
<a rel="previous" href="/code/uth7_floaty-abbrs">
older article →
</a><a rel="next" href="/code/it_figures">
← newer article
</a></nav>
</header>
<!-- =================================================================================================================== -->
<article><header>
<!-- date published or updated -->
<time pubdate datetime="2009-06-07T15:13:00+01:00">
<sup>3:13<abbr>pm</abbr> • 2009</sup>
<abbr title="June">Jun</abbr> 7
</time>
<!-- categories -->
<ul>
<li><a href="/code/php_directory_sorting" rel="bookmark tag">code</a></li>
<li><a href="/web-dev/php_directory_sorting">web-dev</a></li>
</ul>
<!-- licence -->
<small>
<a rel="license" href="http://creativecommons.org/licenses/by/3.0/deed.en_GB">c</a>
share + remix
</small>
</header>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<section>
<h1>Sorting a Directory Listing Folders First, Then by File Type, Then by Name in PHP</h1>
<p>
<strong>Something I think might be useful to people.</strong> This code takes a directory listing and then sorts the
contents listing folders first (in alphabetical order), then the files are sorted by file type and then
alphabetically for each file type.
</p>
<pre><code>//directory to list, you choose; here we’ll just use the webroot
$path = $_SERVER['DOCUMENT_ROOT'];
//warning: `is_dir` will need you to change to the parent directory of what you are testing
//see <uk3.php.net/manual/en/function.is-dir.php#70005> for details
chdir ($path);
//get a directory listing
$dir = array_diff (scandir ('.'),
//folders / files to ignore
array ('.', '..', '.DS_Store', 'Thumbs.db')
);
//sort folders first, then by type, then alphabetically
usort ($dir, create_function ('$a,$b', '
return is_dir ($a)
? (is_dir ($b) ? strnatcasecmp ($a, $b) : -1)
: (is_dir ($b) ? 1 : (
strcasecmp (pathinfo ($a, PATHINFO_EXTENSION), pathinfo ($b, PATHINFO_EXTENSION)) == 0
? strnatcasecmp ($a, $b)
: strcasecmp (pathinfo ($a, PATHINFO_EXTENSION), pathinfo ($b, PATHINFO_EXTENSION))
))
;
'));
//echo to screen
header ('content-type: text/plain');
print_r ($dir);</code></pre>
<p>
Here’s how this breaks down:
</p><p>
<a href="http://uk3.php.net/manual/en/function.usort.php" rel="external"><code>usort</code></a> sorts an array
using another function given two items to compare. Return “-1” if the first should go above the other, 1 if the
second should go above the other and 0 if they are equal.
</p><p>
We create a function with <code>$a</code> and <code>$b</code> parameters corresponding to the two items being
compared for sorting as it goes through the list.
</p>
<pre><code>return is_dir ($a)</code></pre>
<p>
If the first item is a directory then…
</p>
<pre><code>? (is_dir ($b) ? strnatcasecmp ($a, $b) : -1)</code></pre>
<p>
Check if the second item is a directory. If both items are directories then compare them by name.
<a href="http://uk2.php.net/manual/en/function.strnatcasecmp.php" rel="external"><code>strnatcasecmp</code></a>
will return “-1”, “0” or “1” accordingly.
</p>
<pre><code>: (is_dir ($b) ? 1 : (</code></pre>
<p>
Now if the first item is not a directory, check if the second item is. If the second item is a directory, it will go
above the first item—return “1”.
<br /><br />
Else, compare file extensions
</p>
<pre><code>strcasecmp (pathinfo ($a, PATHINFO_EXTENSION), pathinfo ($b, PATHINFO_EXTENSION)) == 0</code></pre>
<p>
If the file extensions are equal then compare the file names
</p>
<pre><code>? strnatcasecmp ($a, $b)</code></pre>
<p>
Finally, if the file extensions are not equal, compare them again, this time returning the result
</p>
<pre><code>: strcasecmp (pathinfo ($a, PATHINFO_EXTENSION), pathinfo ($b, PATHINFO_EXTENSION))</code></pre>
<p>
And that’s it!
<br /><br />
Enjoy.
</p>
</section>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
</article>
<footer>
<nav><a href="http://forum.camendesign.com">‹ Discuss this in the Forum ›</a></nav>
<a href="mailto:kroc@camendesign.com">kroc@camendesign.com</a>
<nav>view-source:
<a href="/code/php_directory_sorting.rem">Rem</a> •
<a href="/code/php_directory_sorting.html">HTML</a> •
<a href="/design/">CSS</a> •
<a href="/.system/">PHP</a> •
<a href="/.htaccess">.htaccess</a>
</nav>
<form method="get" action="https://duckduckgo.com">
<input type="hidden" name="sites" value="camendesign.com" />
<input type="search" name="q" placeholder="search…" />
<input type="submit" value="Go" />
</form>
</footer>
<!-- =================================================================================================== code is art === -->