{"id":3263,"date":"2018-09-08T00:01:59","date_gmt":"2018-09-08T07:01:59","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=3263"},"modified":"2018-09-15T08:39:11","modified_gmt":"2018-09-15T15:39:11","slug":"pulling-a-directory","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=3263","title":{"rendered":"Pulling a Directory"},"content":{"rendered":"<p>O how well I remember DOS. It wasn&#8217;t Unix, but it cribbed from Unix heavily. One of the popular DOS commands was <code>DIR<\/code>, which was like the shell command <em>ls<\/em>, but more primitive. A typical DOS directory listing looked something like this:<br \/>\n<!--more--><\/p>\n<pre class=\"screen\">\r\n Volume in drive C is TOO LOUD\r\n Directory of C:\\PROG\\C\r\n.            &lt;DIR&gt;\r\n..           &lt;DIR&gt;\r\n0901a    c        383   8-18-18   9:42p\r\n0901b    c        506   8-19-18  12:13p\r\n0908     c        796   8-25-18  11:24a\r\n0915     c         44   8-04-18   3:27p\r\na      out       8940   8-25-18  11:24a\r\ngettys~1 txt      177   9-05-15   9:59a\r\nsto          &lt;DIR&gt;\r\n        6 File(s)   bytes free<\/pre>\n<p>The filename came first, split into the 8-character name and 3-character extension. Then came the file&#8217;s size, or <code>&lt;DIR&gt;<\/code> for a directory, followed by the date and time stamp. The <em>cmd<\/em> shell in Windows displays the filename last because the original 8-dot-3 format was discarded long ago; the original format is shown above.<\/p>\n<p>To imitate this format in C, you must extract each filename in the directory, its size, timestamp, and determine whether the file is a directory. From <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3252\">last week&#8217;s Lesson<\/a>, I demonstrated how to use the <em>stat()<\/em> function and <code>S_ISDIR<\/code> macro to pull out directory entries. The two other tidbits required for a DOS-like directory listing are the file&#8217;s size and its timestamp. Both of these items can be pulled from structure returned from the <em>stat()<\/em> function.<\/p>\n<p>A file&#8217;s size is located in the <code>stat<\/code> structure&#8217;s <code>st_size<\/code> member.<\/p>\n<p>The <code>stat<\/code> structure has three members that deal with timestamps:<\/p>\n<p><code>st_atime<\/code>, which returns when file data was last accessed<br \/>\n<code>st_mtime<\/code>, which returns when the file&#8217;s data was last modified<br \/>\n<code>st_ctime<\/code>, which returns when the file&#8217;s status was changed<\/p>\n<p>A fourth member, <code>st_birthtime<\/code>, returns when the file was created, though this member isn&#8217;t available to all operating systems.<\/p>\n<p>You can read more about these fields from my <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3004\">March 24 2018 Lesson here<\/a>.<\/p>\n<p>The following code represents my attempt to ape the old DOS directory command output. I didn&#8217;t bother splitting the filenames between name and extension or cropping long filenames. And I don&#8217;t use the exact format for the timestamp as it would be a bother to extract.<\/p>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;dirent.h&gt;\r\n#include &lt;sys\/stat.h&gt;\r\n#include &lt;unistd.h&gt;\r\n#include &lt;time.h&gt;\r\n\r\nint main()\r\n{\r\n    DIR *folder;\r\n    struct dirent *entry;\r\n    struct stat filestat;\r\n    char cwdpath[256];\r\n    int count = 1;\r\n    long long total = 0;\r\n\r\n    folder = opendir(\".\");\r\n    if(folder == NULL)\r\n    {\r\n        perror(\"Unable to read directory\");\r\n        return(1);\r\n    }\r\n\r\n    <span class=\"comments\">\/* State directory name *\/<\/span>\r\n    getcwd(cwdpath,256);\r\n    printf(\" Directory of %s\\n\\n\",cwdpath);\r\n\r\n    <span class=\"comments\">\/* Read directory entries *\/<\/span>\r\n    while( (entry=readdir(folder)) )\r\n    {\r\n        <span class=\"comments\">\/* Extract Filename *\/<\/span>\r\n        stat(entry-&gt;d_name,&amp;filestat);\r\n        printf(\"%-16s\",entry-&gt;d_name);\r\n\r\n        <span class=\"comments\">\/* Extract Size *\/<\/span>\r\n        if( S_ISDIR(filestat.st_mode) )\r\n            printf(\"%-8s  \",\"&lt;DIR&gt;\");\r\n        else\r\n        {\r\n            printf(\"%8lld  \",filestat.st_size);\r\n            total+=filestat.st_size;\r\n        }\r\n\r\n        <span class=\"comments\">\/* Extract create date and time *\/<\/span>\r\n        printf(\"%s\",ctime(&amp;filestat.st_mtime));\r\n    }\r\n\r\n    closedir(folder);\r\n    printf(\"\\n        %d File(s) for %lld bytes\\n\",\r\n            count,\r\n            total\r\n          );\r\n\r\n    return(0);\r\n}<\/pre>\n<p>For each directory entry read, the <em>stat()<\/em> function fills the <code>filestat<\/code> structure. The file&#8217;s full name is displayed at Line 32. I used a left-justified string output buffer with the placeholder <code>%-16s<\/code>. The 16-character width might be too narrow for some longer filenames.<\/p>\n<p>The <code>filestat.st_mode<\/code> member and <code>S_ISDIR<\/code> macro help pull out directories. Unlike last week&#8217;s example, for a regular file, the <code>filestat.st_size<\/code> member helps read the file&#8217;s size in bytes. This member is typecast as a <em>off_t<\/em> variable, which translates into a <em>long long<\/em> integer and uses the <code>%lld<\/code> placeholder.<\/p>\n<p>The date and time stamp is pulled at Line 44, which is similar to examples in my blog post cited previously in this Lesson.<\/p>\n<p>Here&#8217;s sample output:<\/p>\n<pre class=\"screen\">\r\n Directory of \/Users\/dang\/prog\/c\/blog\r\n\r\n.               &lt;DIR&gt;     Sat Aug 25 12:07:13 2018\r\n..              &lt;DIR&gt;     Sun Aug  5 19:40:28 2018\r\n0901a.c              383  Sat Aug 18 21:42:04 2018\r\n0901b.c              506  Sun Aug 19 12:13:32 2018\r\n0908.c               954  Sat Aug 25 12:07:08 2018\r\n0915.c                44  Sat Aug  4 15:27:24 2018\r\na.out               8940  Sat Aug 25 12:07:13 2018\r\ngettysburg.txt       177  Sat Sep  5 08:59:18 2015\r\nsto             &lt;DIR&gt;     Sat Feb 25 08:06:17 2017\r\n\r\n         9 File(s) for 11004 bytes<\/pre>\n<p>In <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3279\" rel=\"noopener\" target=\"_blank\">next week&#8217;s Lesson<\/a>, I explore recursively spelunking a directory structure.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>O how well I remember DOS. It wasn&#8217;t Unix, but it cribbed from Unix heavily. One of the popular DOS commands was DIR, which was like the shell command ls, but more primitive. A typical DOS directory listing looked something &hellip; <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3263\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-3263","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3263","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3263"}],"version-history":[{"count":6,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3263\/revisions"}],"predecessor-version":[{"id":3299,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3263\/revisions\/3299"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3263"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3263"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3263"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}