{"id":3291,"date":"2018-09-22T00:01:17","date_gmt":"2018-09-22T07:01:17","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=3291"},"modified":"2018-09-15T10:56:56","modified_gmt":"2018-09-15T17:56:56","slug":"recursively-plowing-a-directory-tree","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=3291","title":{"rendered":"Recursively Plowing a Directory Tree"},"content":{"rendered":"<p>The code to recursively plow a directory tree presented in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3279\">last week&#8217;s Lesson<\/a> could be improved upon. Primarily, it relies upon the .. shortcut to jump back to the parent directory. This method works only some of the time.<br \/>\n<!--more--><br \/>\nA problem appears in file structures where symbolic links map directories. In such a configuration, the program can get lost and the parent directory .. is returned as invalid. The solution is to obtain the full pathname, not only for the current directory, but its parent as well.<\/p>\n<p>To get a directory&#8217;s full pathname, use the <em>getcwd()<\/em> function:<\/p>\n<p><code>char *getcwd(char *buf,size_t size);<\/code><\/p>\n<p><em>buf<\/em> is a string representing the directory name, and both the . and .. shortcuts can be used. <em>size<\/em> is the size of the buffer in bytes.<\/p>\n<p>The <em>getcwd()<\/em> function returns a pointer to the buffer. If the function fails, <code>NULL<\/code> is returned. The function is defined in the <code>unistd.h<\/code> header file.<\/p>\n<p>Below I&#8217;ve used the <em>main()<\/em> function from the code presented in last week&#8217;s Lesson as a base. It now obtains the pathname of the current directory, or directory supplied as a command line argument, plus the parent directory name. It then calls the <em>dir()<\/em> function with those two arguments.<\/p>\n<pre class=\"screen\">\r\nint main(int argc, char *argv[])\r\n{\r\n    char current[PATH_MAX],parent[PATH_MAX];\r\n\r\n    puts(\"Finding Directories\");\r\n\r\n    <span class=\"comments\">\/* Change to or set current directory *\/<\/span>\r\n    if(argc==2)\r\n    {\r\n        strcpy(current,argv[1]);\r\n        chdir(current);\r\n    }\r\n    else\r\n    {\r\n        getcwd(current,PATH_MAX);\r\n    }\r\n\r\n    <span class=\"comments\">\/* fetch parent directory *\/<\/span>\r\n    chdir(\"..\");\r\n    getcwd(parent,PATH_MAX);\r\n    <span class=\"comments\">\/* and change back *\/<\/span>\r\n    chdir(current);\r\n    <span class=\"comments\">\/* go! *\/<\/span>\r\n    dir(current,parent);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>The <code>PATH_MAX<\/code> constant is defined by including the <code>limits.h<\/code> header file. Even so, I added some preprocessor directives to ensure that <code>PATH_MAX<\/code> has a value:<\/p>\n<p><code>#ifndef PATH_MAX<br \/>\n#define PATH_MAX 1024<br \/>\n#endif<\/code><\/p>\n<p>Above, if the constant expression <code>PATH_MAX<\/code> doesn&#8217;t exist (or is undefined), the <code>#define<\/code> directive creates it and assigns a value.<\/p>\n<p>The <em>dir()<\/em> function is modified in this code to help track the current and parent directory names: <code>dir(char *directory,char *parent)<\/code><\/p>\n<p>This new function is nearly identical to the original <em>dir()<\/em> function, minus the <code>depth<\/code> argument. The only changes are the use of <em>getcwd()<\/em> to obtain the current directory name, which is output instead of the short name and <code>depth<\/code> indent used in last week&#8217;s code.<\/p>\n<p><a href=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2018\/09\/0922.c\">Click here<\/a> to view the entire code as it&#8217;s a bit long to list in this post. Here&#8217;s sample output:<\/p>\n<pre><code>Finding Directories\r\n\/Users\/dang\/prog\/c\/blog\r\n\/Users\/dang\/prog\/c\/blog\/sto<\/code><\/pre>\n<p>This new code still has a few issues.<\/p>\n<p>First, if you try to run it on the root directory, the program can crash because the root has no parent. Second, if you use the .. shortcut as a command line argument, the program gets lost and displays more information than you intended. Both of these issues can be addressed in the code with a few tests, which I&#8217;ll leave up to you to add.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A better way to dive into the directory depths is to track full pathnames. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3291\">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-3291","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\/3291","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=3291"}],"version-history":[{"count":5,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3291\/revisions"}],"predecessor-version":[{"id":3306,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3291\/revisions\/3306"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3291"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3291"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3291"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}