Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 251
  • Last Modified:

A recursive call quesion

I am writing a ls-like command in unix and I have some troubles when implementing ls -R call.

Currently, my output is something like

file1
file2
sub-directory1
      file3 in sub-directory1
      file4 in sub-directory1
file5
sub-directory2
      file6 sub-directory2

But ls -R output is:

file1
file2
file5

sub-directory1
      file3 in sub-directory1
      file4 in sub-directory1

sub-directory2
      file6 in sub-directory2

I think I made some mistakes in the recursive call. Any help?

Thanks
0
tiger0516
Asked:
tiger0516
  • 2
  • 2
  • 2
  • +1
3 Solutions
 
Kent OlsenData Warehouse Architect / DBACommented:
Hi tiger0516,

Without seeing your code, I suspect that you're processing the files/directories in the current directory in the order that you encounter them.

You'll need to "save" the directories in a table as you encounter them and list the files.  Then process the list of directories.

Or save both in a list, process the directories, then process the files.


Good Luck!
Kent
0
 
tiger0516Author Commented:
>Without seeing your code, I suspect that you're processing the files/directories in the current directory in the order that you encounter them.

Yes,  I did so

>You'll need to "save" the directories in a table as you encounter them and list the files.  Then process the list of directories.

Do you mean a table for all directories? But, for example, a sub directory may have its own sub directory, and so on. Does that matter? I am confused by recursive call if it involves several steps.


0
 
grg99Commented:
if yo want to list all the files first, then the directories, just do:

function show( name )
opendir( name ) while( readdir ) if it's a file, print it.
closedir
opendir( name ) while( readdir ) if it's a directory call show(name\thisdirname)

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Kent OlsenData Warehouse Architect / DBACommented:
Hi tiger0516,

Part of the underlying problem is that some of the functions for reading the contents of a directory are "reentrant", and some are not.  Without knowing which one(s) you're using, I have to assume that you're using non-reentrant code.

Directory and files names within the directory are stored in "random" order.  In general, they're stored in the order that they are created, but deleting of an object leaves a hole that is used by the next item stored so things do get jumbled up.  It's your job (hehehe) to unjumble them as you process the directory.

Assume that we're dealing with a total directory structure like this:

D1
  F1
  F2
  F3
  F4
  D1-1
    G1
    G2
    G3

What you'd like to print is something that looks kind of like that.  (We'll assume that the "." and ".." directories are being ignored.  But what's actually in the directories is this:

D1
  F3
  F2
  D1-1
    G3
    G2
    G1
  F1
  F4

As you process D1, you encounter F3, F2, D1-1, F1, and F4 (in that order).  The challenge is to separate the file(s) in D1 from the directory(ies).  That's where keeping a list comes into play.


Kent
0
 
fridomCommented:
A small remark you do a depth first traversal, obviously ls -R does a breadth first traversal. In you case that would mean:

- if it's file print it's name
- if it's a directory save it away for later use
- if you have exhausted all the files in the current directory, get the first entry from the directory list and apply the function to it as before.

In code this might look like this (assuming you used glib as I did ;-)
#include <glib.h>
#include <glib/gstdio.h>
#include <stdio.h>
#include <stdlib.h>


static void walk_dir (gchar* pathname, gpointer dummy) {

  GList  *dir_names = NULL;
  GDir *dir = NULL;
  GError *err = NULL;
  const gchar *entry = NULL;
  static gint indent = 0;
  gint i;
 
 
  g_chdir(pathname);
  dir = g_dir_open(".", 0, &err);
  for (i = 0; i < indent; i++) {
    putc(' ', stdout);
  }
    g_printf("in %s\n", pathname);
  indent += 2;
  if (NULL == dir) {
    fprintf(stderr, "could not open %s, giving up\n", pathname );
    exit(EXIT_FAILURE);
  }
  while ((entry = g_dir_read_name(dir)) != NULL){
    if (g_file_test (entry, G_FILE_TEST_IS_REGULAR)){
      /* it's a file print it */
      for (i = 0; i < indent; i++) {
        putc(' ', stdout);
      }
     
      g_printf("%s\n", entry);
    } else if (g_file_test(entry, G_FILE_TEST_IS_DIR)){
      indent += 2;
      dir_names = g_list_append(dir_names, (gpointer)entry);
    }
  }
  if (dir_names) {
    g_list_foreach(dir_names, (GFunc) walk_dir, NULL);
  } else {
    if (dir) g_dir_close(dir);
  }
}
   
     
 
int main(void) {
  walk_dir("t1" , NULL);
  return 0;
 
}

output:
ls -R:
ls -R t1
t1:
s1/  t1.txt  t2.txt

t1/s1:
t1.txt

the above written program:
./a.out
in t1
    t1.txt
    t2.txt
    in s1
      t1.txt

IMHO a quite nice solutions, yes I think I like glib ;-)

Regards
Friedrich
0
 
tiger0516Author Commented:
Come on, man. Why you appeared so late @@
0
 
fridomCommented:
Late?? just 12 hours after your posting? You are quite aware this is a forum, and not an IRC? ;)

Regards
Friedrich

0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 2
  • 2
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now