{"id":3252,"date":"2018-09-01T00:01:03","date_gmt":"2018-09-01T07:01:03","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=3252"},"modified":"2021-10-30T15:30:26","modified_gmt":"2021-10-30T22:30:26","slug":"directory-entry-file-types","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=3252","title":{"rendered":"Directory Entry File Types"},"content":{"rendered":"<p>Not every file listed in a directory is the same. Some entries represent other directories, subdirectories, for example. To determine which entries are mere mortal files and which are directories, you must examine the file type.<br \/>\n<!--more--><br \/>\nThe good news is that file type information is held in the same <code>dirent<\/code> structure that yields the file&#8217;s name. The structure member is <code>d_type<\/code>. The bad news is that not every operating system features the <code>d_type<\/code> member in its <code>dirent<\/code> structure.<\/p>\n<p>The following code modifies the second example from <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3246\">last week&#8217;s Lesson<\/a> to display the <code>d_type<\/code> member&#8217;s value for the current directory:<\/p>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;dirent.h&gt;\r\n\r\nint main()\r\n{\r\n    DIR *folder;\r\n    struct dirent *entry;\r\n    int files = 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    while( (entry=readdir(folder)) )\r\n    {\r\n        files++;\r\n        printf(\"File %3d: %s, %d\\n\",\r\n                files,\r\n                entry-&gt;d_name,\r\n                entry-&gt;d_type\r\n              );\r\n    }\r\n\r\n    closedir(folder);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>The only modification to this code from what was shown last week is the <em>printf()<\/em> statement starting at Line 20. I added the <code>entry-&gt;d_type<\/code> item and used the <code>%d<\/code> placeholder to display its integer value. Here&#8217;s sample output:<\/p>\n<pre><code>File   1: .,4\r\nFile   2: ..,4\r\nFile   3: 0825a.c,8\r\nFile   4: 0825b.c,8\r\nFile   5: 08exercise-a.c,8\r\nFile   6: 08exercise-b.c,8\r\nFile   7: 0901.c,8\r\nFile   8: 0908.c,8\r\nFile   9: a.out,8\r\nFile  10: gettysburg.txt,8\r\nFile  11: sto,4<\/code><\/pre>\n<p>The values returned are specific to the operating system. Under Unix, value 8 is a regular file and 4 is a directory. On my PC, the MinGW compiler&#8217;s C library lacks the <code>dirent-&gt;d_type<\/code> member. So the code doesn&#8217;t compile. That&#8217;s okay, because a better way is available to read whether a directory entry is a file or directory: Use the <em>stat()<\/em> function, as defined in the <code>sys\/stat.h<\/code> header file:<\/p>\n<p><code>int stat(const char *restrict path, struct stat *restrict buf);<\/code><\/p>\n<p>The <em>stat()<\/em> function requires two arguments. The first is the name (or pathname) to a filename. The second argument is the address of a <code>stat<\/code> structure. This structure is filled with oodles of good info about a directory entry and it&#8217;s consistent across all file systems.<\/p>\n<p>The <code>sys\/stat.h<\/code> header file also defines macros to test for file type, which work similarly to the <code>ctype.h<\/code> macros that examine characters. For a directory entry, the <code>S_ISDIR<\/code> macro is used:<\/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\r\nint main()\r\n{\r\n    DIR *folder;\r\n    struct dirent *entry;\r\n    struct stat filestat;\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\">\/* Read directory entries *\/<\/span>\r\n    while( (entry=readdir(folder)) )\r\n    {\r\n        stat(entry-&gt;d_name,&amp;filestat);\r\n        if( S_ISDIR(filestat.st_mode) )\r\n            printf(\"%4s: %s\\n\",\"Dir\",entry-&gt;d_name);\r\n        else\r\n            printf(\"%4s: %s\\n\",\"File\",entry-&gt;d_name);\r\n    }\r\n    closedir(folder);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>The <em>stat()<\/em> function appears at Line 21. Its arguments are the name of the file located in the directory (<code>entry-&gt;d_name<\/code>) and the address of the <code>stat<\/code> structure <code>filestat<\/code>, declared at Line 9.<\/p>\n<p>In Line 22, the <code>S_ISDIR<\/code> macro tests the <code>filestat.st_mode<\/code> member. If true, the entry is a directory and it&#8217;s flagged as such in the output. Otherwise, the <em>else<\/em> statement flags the entry as a standard file.<\/p>\n<p>Here&#8217;s sample output:<\/p>\n<pre><code> Dir: .\r\n Dir: ..\r\nFile: 0825a.c\r\nFile: 0825b.c\r\nFile: 08exercise-a.c\r\nFile: 08exercise-b.c\r\nFile: 0901a.c\r\nFile: 0901b.c\r\nFile: 0908.c\r\nFile: a.out\r\nFile: gettysburg.txt\r\n Dir: sto<\/code><\/pre>\n<p>This code runs on both the PC and Unix systems, thanks to the <em>stat()<\/em> function.<\/p>\n<p>You can pull more details from the <em>stat()<\/em> function, including file size and timestamps. I&#8217;ll cover that process in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3263\">next week&#8217;s Lesson<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The <code>dirent<\/code> structure contains not only a directory entry&#8217;s filename, but what kind of file it is. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3252\">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-3252","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\/3252","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=3252"}],"version-history":[{"count":7,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3252\/revisions"}],"predecessor-version":[{"id":5055,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3252\/revisions\/5055"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3252"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3252"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3252"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}