{"id":4482,"date":"2009-10-22T16:40:50","date_gmt":"2009-10-22T23:40:50","guid":{"rendered":"http:\/\/css-tricks.com\/?page_id=4482"},"modified":"2018-08-21T07:14:18","modified_gmt":"2018-08-21T14:14:18","slug":"display-styled-directory-contents","status":"publish","type":"page","link":"https:\/\/css-tricks.com\/snippets\/php\/display-styled-directory-contents\/","title":{"rendered":"Display Styled Directory Contents"},"content":{"rendered":"

Servers can be configured to show the contents of a directory that doesn’t have an index file to render. The result is usually less than visually spectacular:<\/p>\n

\"\"
Lackluster default in Chrome<\/figcaption><\/figure>\n
\"\"
More better, View Demo<\/a><\/figcaption><\/figure>\n

We can take control of this ourselves by replicating this functionality with PHP. <\/p>\n

    \n
  1. Make an index file (.index.php<\/code>, starting with the dot, really) which reads the files in the directory and outputs them into a table<\/li>\n
  2. Make an .htaccess<\/code> file that serves that file as the index<\/li>\n
  3. Have the index file load in CSS and other resources that are also prefixed with a dot (hidden)<\/li>\n<\/ol>\n

    The following PHP reads the directory of files and displays a styled table of their name, file type, and file size. It also applies a class name in which to apply icons for the different major file types (see CSS).<\/p>\n

    <!doctype html>\r\n<html>\r\n\r\n<head>\r\n  <meta charset=\"UTF-8\">\r\n  <title>Directory Contents<\/title>\r\n  <link rel=\"stylesheet\" href=\".style.css\">\r\n  <script src=\".sorttable.js\"><\/script>\r\n<\/head>\r\n\r\n<body>\r\n\r\n  <div id=\"container\">\r\n  \r\n    <h1>Directory Contents<\/h1>\r\n    \r\n    <table class=\"sortable\">\r\n      <thead>\r\n        <tr>\r\n          <th>Filename<\/th>\r\n          <th>Type<\/th>\r\n          <th>Size <small>(bytes)<\/small><\/th>\r\n          <th>Date Modified<\/th>\r\n        <\/tr>\r\n      <\/thead>\r\n      <tbody>\r\n      <?php\r\n        \/\/ Opens directory\r\n        $myDirectory=opendir(\".\");\r\n        \r\n        \/\/ Gets each entry\r\n        while($entryName=readdir($myDirectory)) {\r\n          $dirArray[]=$entryName;\r\n        }\r\n        \r\n        \/\/ Finds extensions of files\r\n        function findexts ($filename) {\r\n          $filename=strtolower($filename);\r\n          $exts=split(\"[\/\\\\.]\", $filename);\r\n          $n=count($exts)-1;\r\n          $exts=$exts[$n];\r\n          return $exts;\r\n        }\r\n        \r\n        \/\/ Closes directory\r\n        closedir($myDirectory);\r\n        \r\n        \/\/ Counts elements in array\r\n        $indexCount=count($dirArray);\r\n        \r\n        \/\/ Sorts files\r\n        sort($dirArray);\r\n        \r\n        \/\/ Loops through the array of files\r\n        for($index=0; $index < $indexCount; $index++) {\r\n        \r\n          \/\/ Allows .\/?hidden to show hidden files\r\n          if($_SERVER['QUERY_STRING']==\"hidden\")\r\n          {$hide=\"\";\r\n          $ahref=\".\/\";\r\n          $atext=\"Hide\";}\r\n          else\r\n          {$hide=\".\";\r\n          $ahref=\".\/?hidden\";\r\n          $atext=\"Show\";}\r\n          if(substr(\"$dirArray[$index]\", 0, 1) != $hide) {\r\n          \r\n          \/\/ Gets File Names\r\n          $name=$dirArray[$index];\r\n          $namehref=$dirArray[$index];\r\n          \r\n          \/\/ Gets Extensions \r\n          $extn=findexts($dirArray[$index]); \r\n          \r\n          \/\/ Gets file size \r\n          $size=number_format(filesize($dirArray[$index]));\r\n          \r\n          \/\/ Gets Date Modified Data\r\n          $modtime=date(\"M j Y g:i A\", filemtime($dirArray[$index]));\r\n          $timekey=date(\"YmdHis\", filemtime($dirArray[$index]));\r\n          \r\n          \/\/ Prettifies File Types, add more to suit your needs.\r\n          switch ($extn){\r\n            case \"png\": $extn=\"PNG Image\"; break;\r\n            case \"jpg\": $extn=\"JPEG Image\"; break;\r\n            case \"svg\": $extn=\"SVG Image\"; break;\r\n            case \"gif\": $extn=\"GIF Image\"; break;\r\n            case \"ico\": $extn=\"Windows Icon\"; break;\r\n            \r\n            case \"txt\": $extn=\"Text File\"; break;\r\n            case \"log\": $extn=\"Log File\"; break;\r\n            case \"htm\": $extn=\"HTML File\"; break;\r\n            case \"php\": $extn=\"PHP Script\"; break;\r\n            case \"js\": $extn=\"Javascript\"; break;\r\n            case \"css\": $extn=\"Stylesheet\"; break;\r\n            case \"pdf\": $extn=\"PDF Document\"; break;\r\n            \r\n            case \"zip\": $extn=\"ZIP Archive\"; break;\r\n            case \"bak\": $extn=\"Backup File\"; break;\r\n            \r\n            default: $extn=strtoupper($extn).\" File\"; break;\r\n          }\r\n          \r\n          \/\/ Separates directories\r\n          if(is_dir($dirArray[$index])) {\r\n            $extn=\"&lt;Directory&gt;\"; \r\n            $size=\"&lt;Directory&gt;\"; \r\n            $class=\"dir\";\r\n          } else {\r\n            $class=\"file\";\r\n          }\r\n          \r\n          \/\/ Cleans up . and .. directories \r\n          if($name==\".\"){$name=\". (Current Directory)\"; $extn=\"&lt;System Dir&gt;\";}\r\n          if($name==\"..\"){$name=\".. (Parent Directory)\"; $extn=\"&lt;System Dir&gt;\";}\r\n          \r\n          \/\/ Print 'em\r\n          print(\"\r\n          <tr class='$class'>\r\n            <td><a href='.\/$namehref'>$name<\/a><\/td>\r\n            <td><a href='.\/$namehref'>$extn<\/a><\/td>\r\n            <td><a href='.\/$namehref'>$size<\/a><\/td>\r\n            <td sorttable_customkey='$timekey'><a href='.\/$namehref'>$modtime<\/a><\/td>\r\n          <\/tr>\");\r\n          }\r\n        }\r\n      ?>\r\n      <\/tbody>\r\n    <\/table>\r\n  \r\n    <h2><?php print(\"<a href='$ahref'>$atext hidden files<\/a>\"); ?><\/h2>\r\n    \r\n  <\/div>\r\n  \r\n<\/body>\r\n\r\n<\/html><\/code><\/pre>\n

    The resources loaded in that index file are the top-in table sorter script sortable.js<\/a> and a .style.css file. (Remember, prefacing the files with a dot makes the invisible in most operating systems, and also won’t show up in your directory of files (good)). Here’s that CSS:<\/p>\n

    * {\r\n  padding:0;\r\n  margin:0;\r\n}\r\n\r\nbody {\r\n  color: #333;\r\n  font: 14px Sans-Serif;\r\n  padding: 50px;\r\n  background: #eee;\r\n}\r\n\r\nh1 {\r\n  text-align: center;\r\n  padding: 20px 0 12px 0;\r\n  margin: 0;\r\n}\r\n\r\nh2 {\r\n  font-size: 16px;\r\n  text-align: center;\r\n  padding: 0 0 12px 0; \r\n}\r\n\r\n#container {\r\n  box-shadow: 0 5px 10px -5px rgba(0,0,0,0.5);\r\n  position: relative;\r\n  background: white; \r\n}\r\n\r\ntable {\r\n  background-color: #F3F3F3;\r\n  border-collapse: collapse;\r\n  width: 100%;\r\n  margin: 15px 0;\r\n}\r\n\r\nth {\r\n  background-color: #FE4902;\r\n  color: #FFF;\r\n  cursor: pointer;\r\n  padding: 5px 10px;\r\n}\r\n\r\nth small {\r\n  font-size: 9px; \r\n}\r\n\r\ntd, th {\r\n  text-align: left;\r\n}\r\n\r\na {\r\n  text-decoration: none;\r\n}\r\n\r\ntd a {\r\n  color: #663300;\r\n  display: block;\r\n  padding: 5px 10px;\r\n}\r\n\r\nth a {\r\n  padding-left: 0\r\n}\r\n\r\ntd:first-of-type a {\r\n  background: url(.\/.images\/file.png) no-repeat 10px 50%;\r\n  padding-left: 35px;\r\n}\r\n\r\nth:first-of-type {\r\n  padding-left: 35px;\r\n}\r\n\r\ntd:not(:first-of-type) a {\r\n  background-image: none !important;\r\n} \r\n\r\ntr:nth-of-type(odd) {\r\n  background-color: #E6E6E6;\r\n}\r\n\r\ntr:hover td {\r\n  background-color:#CACACA;\r\n}\r\n\r\ntr:hover td a {\r\n  color: #000;\r\n}\r\n\r\n\/* icons for file types (icons by famfamfam) *\/\r\n\r\n\/* images *\/\r\ntable tr td:first-of-type a[href$=\".jpg\"], \r\ntable tr td:first-of-type a[href$=\".png\"], \r\ntable tr td:first-of-type a[href$=\".gif\"], \r\ntable tr td:first-of-type a[href$=\".svg\"], \r\ntable tr td:first-of-type a[href$=\".jpeg\"] {\r\n  background-image: url(.\/.images\/image.png);\r\n}\r\n\r\n\/* zips *\/\r\ntable tr td:first-of-type a[href$=\".zip\"] {\r\n  background-image: url(.\/.images\/zip.png);\r\n}\r\n\r\n\/* css *\/\r\ntable tr td:first-of-type a[href$=\".css\"] {\r\n  background-image: url(.\/.images\/css.png);\r\n}\r\n\r\n\/* docs *\/\r\ntable tr td:first-of-type a[href$=\".doc\"],\r\ntable tr td:first-of-type a[href$=\".docx\"],\r\ntable tr td:first-of-type a[href$=\".ppt\"],\r\ntable tr td:first-of-type a[href$=\".pptx\"],\r\ntable tr td:first-of-type a[href$=\".pps\"],\r\ntable tr td:first-of-type a[href$=\".ppsx\"],\r\ntable tr td:first-of-type a[href$=\".xls\"],\r\ntable tr td:first-of-type a[href$=\".xlsx\"] {\r\n  background-image: url(.\/.images\/office.png)\r\n}\r\n\r\n\/* videos *\/\r\ntable tr td:first-of-type a[href$=\".avi\"], \r\ntable tr td:first-of-type a[href$=\".wmv\"], \r\ntable tr td:first-of-type a[href$=\".mp4\"], \r\ntable tr td:first-of-type a[href$=\".mov\"], \r\ntable tr td:first-of-type a[href$=\".m4a\"] {\r\n  background-image: url(.\/.images\/video.png);\r\n}\r\n\r\n\/* audio *\/\r\ntable tr td:first-of-type a[href$=\".mp3\"], \r\ntable tr td:first-of-type a[href$=\".ogg\"], \r\ntable tr td:first-of-type a[href$=\".aac\"], \r\ntable tr td:first-of-type a[href$=\".wma\"] {\r\n  background-image: url(.\/.images\/audio.png);\r\n}\r\n\r\n\/* web pages *\/\r\ntable tr td:first-of-type a[href$=\".html\"],\r\ntable tr td:first-of-type a[href$=\".htm\"],\r\ntable tr td:first-of-type a[href$=\".xml\"] {\r\n  background-image: url(.\/.images\/xml.png);\r\n}\r\n\r\ntable tr td:first-of-type a[href$=\".php\"] {\r\n  background-image: url(.\/.images\/php.png);\r\n}\r\n\r\ntable tr td:first-of-type a[href$=\".js\"] {\r\n  background-image: url(.\/.images\/script.png);\r\n}\r\n\r\n\/* directories *\/\r\ntable tr.dir td:first-of-type a {\r\n  background-image: url(.\/.images\/folder.png);\r\n}<\/code><\/pre>\n

    View Demo<\/a>   Download Files<\/a><\/p>\n

    REMEMBER:<\/strong> The .zip file might appear to be empty, but it’s not. The files are all prefaced with a dot. View them in a file editor which shows you “hidden” files. <\/p>\n

    \"\"<\/p>\n

    Special thanks to Cliff White.<\/p>\n

    Update November 2012: The demo and downloadable files have been updated to (1) show more human readable file sizes (2) have error pages<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"

    Servers can be configured to show the contents of a directory that doesn’t have an index file to render. The result is usually less than visually spectacular: Lackluster default in Chrome More better, View Demo We can take control of this ourselves by replicating this functionality with PHP. Make an index file (.index.php, starting with […]<\/p>\n","protected":false},"author":3,"featured_media":0,"parent":3233,"menu_order":0,"comment_status":"open","ping_status":"closed","template":"page-snippet.php","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":""},"tags":[],"acf":[],"jetpack-related-posts":[{"id":3942,"url":"https:\/\/css-tricks.com\/snippets\/htaccess\/different-directory-index-page\/","url_meta":{"origin":4482,"position":0},"title":"Different Directory Index Page","date":"September 8, 2009","format":false,"excerpt":"Normally index.html or index.php is the default page a server serves up when visiting a directory without specifying a file name. You can change this with .htaccess: DirectoryIndex index2.html","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4232,"url":"https:\/\/css-tricks.com\/snippets\/htaccess\/password-protect-folders\/","url_meta":{"origin":4482,"position":1},"title":"Password Protect Folder(s)","date":"September 25, 2009","format":false,"excerpt":"Put in .htaccess file in the directory you are trying to protect: AuthType Basic AuthName \"This Area is Password Protected\" AuthUserFile \/full\/path\/to\/.htpasswd Require valid-user Ideally, the .htpasswd file will be not in a public facing directory. Put this in there: chriscoyier:$apr1$O\/BJv...$vIHV9Q7ySPkw6Mv6Kd\/ZE\/ That is just a sample, you can create the\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4922,"url":"https:\/\/css-tricks.com\/snippets\/php\/increase-maximum-php-upload-size\/","url_meta":{"origin":4482,"position":2},"title":"Increase Maximum PHP Upload Size","date":"December 3, 2009","format":false,"excerpt":"Many shared hosts put very low restrictions on the size of the files that can be uploaded through PHP. But, many hosts also allow you to create your own php.ini file in the root directory of your site. This file can override some of the servers default PHP settings. If\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":207270,"url":"https:\/\/css-tricks.com\/snippets\/html\/start-a-web-server-with-one-terminal-command-on-os-x\/","url_meta":{"origin":4482,"position":3},"title":"Start a Web Server With One Terminal Command on OS X","date":"August 27, 2015","format":false,"excerpt":"I've searched for this three times this week, so I figured I'd better make sure I have a copy of it. Python 2: python -m SimpleHTTPServer 8000 Navigate to the project directory in the terminal and do that command. Then http:\/\/localhost:8000 will server up that directory (as in, it's `index.html`\u2026","rel":"","context":"In \"php\"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4030,"url":"https:\/\/css-tricks.com\/snippets\/htaccess\/force-favicon-requests-to-correct-location\/","url_meta":{"origin":4482,"position":4},"title":"Force Favicon Requests to Correct Location","date":"September 11, 2009","format":false,"excerpt":"For whatever crazy reason, perhaps evil-doing site scanners, requets to a web server for a favicon in all known crevasses of the site are fairly common. Since that file probably only actually exists in the root directory of your site, these requests result in a 404. If you server up\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":16899,"url":"https:\/\/css-tricks.com\/snippets\/php\/create-data-uris\/","url_meta":{"origin":4482,"position":5},"title":"Create Data URI’s","date":"May 1, 2012","format":false,"excerpt":"These can be useful for embedding images into HTML\/CSS\/JS to save on HTTP requests, at the cost of maintainability. More information. There are online tools to do it, but if you want your own very simple utility, here's some PHP to do it: function data_uri($file, $mime) { $contents=file_get_contents($file); $base64=base64_encode($contents); echo\u2026","rel":"","context":"With 6 comments","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/pages\/4482"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=4482"}],"version-history":[{"count":11,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/pages\/4482\/revisions"}],"predecessor-version":[{"id":275558,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/pages\/4482\/revisions\/275558"}],"up":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/pages\/3233"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=4482"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=4482"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}