LinuxQuestions.org
Visit the LQ Articles and Editorials section
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 03-05-2007, 09:45 PM   #1
nadroj
Senior Member
 
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539

Rep: Reputation: 59
writing a recursive 'find' command


im working on a homework assignment. the assignment is to write a simple unix 'myFind' command with synopsis: find <filename>. it searches current directory and every subdirectory and prints the path of each file whos name is <filename>.

after some debugging, i thought it would be easier to basically make it a recursive 'ls' command, as my find isnt working. the 'ls' isnt working either. when i run from my home directory it seems to work fine. however, if i run from / or /usr (maybe more directories too) it does not work.

when i run from / it gets stuck searching in a weird directory (which doesnt exist) like /dev/fd/3/0/dev/fd/3/cpu/bin/dev/3...etc

when i run from /usr it also doesnt work properly. if i run it from /usr, as "./myFind | grep stdio.h" it returns no output. however, there are multiple files in subdirectories of this folder named stdio.h.

i have tried using stat but it isnt helping so i stopped with that. i have emailed my professor asking if we have to check if a file is a link, device, etc, and he said we dont have to, and also that we do not _have_ to use stat to do this assignment. i would like to do it without stat.

heres the code if you have time to check it out.
Code:
#include <dirent.h> 
#include <unistd.h> 
#include <stdio.h> 
#include<string.h>

void search(char* path)
{
	DIR* dp;

	dp = opendir(path);

	if (dp == NULL)
	{
		printf("cant open: %s\n",path);
		return;
	}

	struct dirent* dirp;
	while( (dirp = readdir(dp)) != NULL )
	{
		if (strcmp(dirp->d_name,".") == 0 || strcmp(dirp->d_name,"..") == 0)
			continue;

		printf("%s%s\n", path,dirp->d_name);

		char tmpPath[256]="";
		strcat(tmpPath,path);
		strcat(tmpPath,dirp->d_name);
		strcat(tmpPath,"/");

		search(tmpPath);
	}
	
}

int main(int argc, char* argv[])
{
	search("./");
}
thanks for your time.

edit:
from my home directory (with a deep arbitrarily copied hierarchy) it lists the files, including one named:
Quote:
./subtest/subdir/test/cvx/dfgd/sdf/fgh/ghj/acpi/events/alsa/sound/linux-2.4.33.3/arch/m68k/sun3/config.c
the reason im including this is to show that it is looking in complicated and deep subdirectories such as the one above. this (and the /dev/... thing above) leads me to think that there must be a problem with files that are not regular files or directories. however, my professor told me it can be done without checking for this.

Last edited by nadroj; 03-05-2007 at 09:53 PM.
 
Old 03-05-2007, 11:10 PM   #2
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379

Rep: Reputation: 148Reputation: 148
When reading the contents of a directory, the directory may consist of files and other directories. So you need to determine if the current directory element you are looking at is a file or a directory. Only if it is a directory will you want to do a recursive call to search.
 
Old 03-05-2007, 11:26 PM   #3
nadroj
Senior Member
 
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539

Original Poster
Rep: Reputation: 59
is the only way to determine this to use 'stat'?

my code does 'kind of' take care of what your talking about. after the recursive call in the while loop, i call opendir on the directory passed to search. if the opendir call was NULL, then the path passed to the function was referring to a file, and the function returns.

it seems to work the way i have it (only in my home directory). or do you still see a specific problem with doing it this way?
 
Old 03-05-2007, 11:39 PM   #4
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379

Rep: Reputation: 148Reputation: 148
using stat() would be the way that I would check it, using the st_mode element of the stat structure, and the S_IFDIR flag. I would say that it is more efficient to test and then only do the recursive call for directories. To me it is also cleaner. You don't need to worry about the special files . .. and you can also decide to follow or not to follow symbolic links.
 
Old 03-06-2007, 12:10 AM   #5
nadroj
Senior Member
 
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539

Original Poster
Rep: Reputation: 59
thanks for your help (forgot to say previously).
i was trying earlier with stat and couldnt get it to work, so i tried to do it without stat.

im now trying to do it and im getting the same lack of success.
i will post how i modified the body of the while loop.
Code:
 while( (dirp = readdir(dp)) != NULL )
        {
                if (strcmp(dirp->d_name,".") == 0 || strcmp(dirp->d_name,"..") == 0)
                        continue;
 
                printf("%s%s\n", path,dirp->d_name);
 
                struct stat buf;
                stat(dirp->d_name, &buf);
        
                if (buf.st_mode == S_IFDIR)
                {
                        char tmpPath[256]="";
                        strcat(tmpPath,path);
                        strcat(tmpPath,dirp->d_name);
                        strcat(tmpPath,"/");
        
                        search(tmpPath);
                }
        }
from what i have read, you can use either the method you described (which is shown here) or another method, to check if the dirent* is a file. you can also check: if (S_ISDIR(buf.st_mode))
i have tried both just now and it just seems to list everything in the current directory.

i tested with a printf inside the if statement comparing buf.st_mode and it never prints.

edit: i think im getting somewhere.. will post back tomorrow.

Last edited by nadroj; 03-06-2007 at 01:39 AM.
 
Old 03-06-2007, 02:06 AM   #6
graemef
Senior Member
 
Registered: Nov 2005
Location: Hanoi
Distribution: Fedora 13, Ubuntu 10.04
Posts: 2,379

Rep: Reputation: 148Reputation: 148
First print out buf.st_mode. It might be easier to understand what is going on if you look at the value in hex mode.

Then rather than doing an equivalence comparison == you need to look at the individual bits. S_IFDIR is a flag so you want to do a bitwise comparison, something like:
if (buf.st_mode & S_IFDIR)
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
recursive find dhaus111 Linux - Newbie 10 01-11-2007 01:59 AM
Recursive, comm, find, PDFs zamdrist Linux - General 3 11-13-2006 11:56 PM
can 'ls' command be recursive? Hailey's_Comet Linux - Newbie 3 10-01-2006 01:29 AM
the lovely recursive(-R) command mikeghet Linux - Newbie 3 12-23-2004 04:46 PM
call recursive find except on ./foo/ Hano Linux - General 1 07-30-2002 02:08 PM


All times are GMT -5. The time now is 02:21 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration