UP | HOME

File System (fs) Project
COP-3402

Table of Contents

1. Overview

In this project, you will implement a variation of the find and wc commands called myfind. This tool will recursively list out all files in the source tree (in any order).

2. Input

USAGE: myfind [-l] path

EXAMPLES:
myfind file.c
myfind dirfile
myfind dirfile/file.c
myfind dirfile/subdir/file
myfind -l dirfile/subdir/file.c

The program should be called myfind. It takes one argument and one optional flag. path is any absolute or relative path. If a non-directory file is given, it will only list that one file. A directory file will have all files in its directory listed and recursively follow any subdirectories

Add a flag "-l" to list out the number of lines (number of '\n' characters) in regular file

2.1. Error conditions

In the following cases, exit immediately with EXIT_FAILURE:

  • If there are no arguments to the program
  • If there are two arguments but the first is a not the "-l" flag.

In the following cases, skip printing the file

  • The file or directory doesn't exist, lacks necessary permissions, or cannot be opened, read, and closed for any other reason

3. Output

The output should be a list of the paths to each file to standard out, starting with the input path given as the command-line argument. If the -l flag is set, then the number of lines in the file as a integer should be printed after the filename, separated by a tab \t (see Format strings for the exact strings to use for printing output).

3.1. Example

If a construct a new directory tree like this

mkdir contents
mkdir contents/subdir
touch contents/file1
echo -ne "1\n2\n3" > contents/file2
echo -ne "1\n2\n3\n4\n" > contents/subdir/file3

and then run myfind on it like this:

./myfind -l contents

I should see the following output:

contents
contents/subdir
contents/subdir/file3	4
contents/file2	2
contents/file1	0  

Where the space between the file name and the number of lines is a single tab character (\t).

See Grading for some automated test cases.

4. Implementation

For each file in the file tree starting from path:

  • If it's a directory file, list its name, then recurse over each file in the directory, except for . and ... Note that the tool should accept . or .. as arguments to the tool. Just be sure not to recursively traverse these directories.)
  • If it's a regular file, list its name, then also list the number of lines in the file, i.e., the number of newline characters ('\n')
  • If it's any other kind of file, list its name only
  • If the file doesn't exist, or cannot be open, etc., skip it

Error messages are optional, but should only be written to stderr, not to stdout, which will be used for program output, i.e., use fprintf(stderr, ...) instead of printf.

4.1. Format strings

File Type Format String
Regular (no -l) "%s\n"
Regular (with -l) "%s\t%ld\n"
Directory "%s\n"
Other "%s\n"

Be sure to print the entire path for each file, i.e., the given path argument joined with the path separator character ("/").

4.2. System call and library references

Do not use helper libraries or other simplified calls to achieve similar results as functions below. Just use the syscalls or library functions below for these aspects of the project.

Symbol Reference Reading
stat() man 2 stat LPI 15.1
struct stat man 3 stat  
st_mode man 7 inode  
opendir() man 3 opendir LPI 18.8
readdir() man 3 readdir  
closedir() man 3 closedir  
struct dirent * man 3 readdir  
open() man 2 open LPI 4.1
read() man 2 read  
write() man 2 write  
close() man 2 close  
perror() man 3 perror LPI 3.4
exit(EXIT_FAILURE) man 3 exit  
  • man is the command-line manual.
  • LPI is The Linux Program Interface book.
  • Knowledge of memory management and string processing is assumed.

4.3. Example header files

These are a set of header files that is sufficient for completing the project:

#include <fcntl.h>         // O_RDONLY, O_WRONLY, O_CREAT, open
#include <errno.h>         // errno
#include <stdio.h>         // perror, fprintf
#include <dirent.h>        // opendir, readdir, DIR, struct dirent
#include <stdlib.h>        // exit
#include <sys/stat.h>      // stat
#include <assert.h>        // assert
#include <string.h>        // string.h
#include <unistd.h>        // read, write, close
#include <stdbool.h>       // bool

4.4. Joining paths

Be sure when concenating strings for the paths that you malloc enough space for the entire new string plus the additional path separator and plus the null terminator for the string, e.g.,

// len + separator + len + terminator
int concatlen = strlen(curpath) + 1 + strlen(curdir->d_name) + 1;
char *newpath = malloc(concatlen * sizeof(char));
if (NULL == newpath) {
  perror("malloc");
  exit(EXIT_FAILURE);
}
snprintf(newpath, concatlen, "%s/%s", curpath, curdir->d_name);

The grading tests will not put a path separator character at the end of the path, even if its a directory. In testing, if you do have a path separator, then joining by string concanetion may result in a double path separator, e.g., subdir//file, which should be harmless.

5. Building and running the tool

Create a Makefile that will build your project and give the resulting program the name myfind. See the hello project for an example Makefile.

Your project must be buildable with make and runnable with ./myfind, both from the root of your repo, i.e.,

cd ~/cop3402fall25/fs
make
./myfind

Automated grading will build and run your tool this way and only this way.

6. Submitting your project

6.1. git setup

Be sure to complete the vc exercise before attempting this project.

Create a new local repository, following the directions in the vc exercise (including the git --set-upstream last step) and set the local and remote repository URLs to be the following locations:

Local repository ~/cop3402fall25/fs
Remote repository gitolite3@eustis3.eecs.ucf.edu:cop3402/$USER/fs

Commands

These steps only setup the repo, do not submit your code, and assume you have already completed the vc exercise. Consult that exercise for specifics on validating each step and submitting your code.

mkdir -p ~/cop3402fall25/fs
cd ~/cop3402fall25/fs
git init
echo "fs project" > README.md
git add README.md
git commit README.md
# Enter a commit message in the editor that pops up
git remote add submission gitolite3@eustis3.eecs.ucf.edu:cop3402/$USER/fs
git push --set-upstream submission master

6.2. Self-check

See the hello project for instructions on cloning a project from the grading server.

7. Bonus features

7.1. Implement a file type filter

Implement a file type filter option. This option will either limit the results to either only regular files or only directory files. The option will either be --type f to limit to only regular files or --type d to limit to only regular files. Without this option, there should be no filtering as in the non-bonus project requirements. Here is an example:

Take the following directory structure, where dir1 and dir2 are directory files while file1, file2, and file3 are regular files:

.
├── dir1
│   ├── file1
│   └── file2
├── dir2
└── file3

Running ./myfind --type f . should yield the following (in any order):

./file3
./dir1/file2
./dir1/file1

Running ./myfind --type d . should yield the following (in any order):

.
./dir2
./dir1

7.2. Notes

  • These options will require allowing for up to three arguments by the tool without exiting with an error. This won't affect scoring, since this isn't tested.
  • Be sure to allow any ordering of options, i.e., --type, and -l may appear in any order.
  • Note that argv will have two separate array slots for the option name and the parameter to that name, e.g., -type and f may be argv[1] and argv[2] respectively. These indices may differ depending on the order of options given by the user on the command-line).
  • You may use the getopt library if you want to make option processing easier.
  • Bonus points will be graded mechanically, but test cases will not be released. Please develop your own test cases and use the examples given above.
  • The file type is not its extension. Where can we see whether the file is a regular file or a directory file?
  • The non-bonus requirements for recursively traverses subdirectories and using -l still apply.

8. Grading

The test cases used to grade the project are listed below. Scripts to run the the odd-numbered test cases are provided publicly, while the even-numbered test cases are private.

To use the automated tests, first download them, e.g.,

cd ~/cop3402fall25/fs
wget https://www.cs.ucf.edu/~gazzillo/teaching/cop3402fall25/files/fs_public_tests.tar
tar -xvf fs_public_tests.tar

To run a test case, e.g., tests/03.sh, use the following bash command from the root of your local repository directory:

bash fs-tests/03.sh $(realpath myfind)
echo $?

This runs the bash script, passing in the absolute path to your program, which is what $(realpath myfind) does. The result of echo $? should be 0 which indicates the test was succesful.

8.1. Test cases

# Description Expected Output
1 Call myfind with no arguments It should fail with the appropriate exit code.
2 Call myfind with an invalid option (not -l) It should fail with the appropriate exit code.
3 Call myfind with a single empty file It should print the file name
4 Call myfind with a path to an empty directory It should only print the directory path
5 Call myfind with a path to a directory with no subdirectories It should print the directory path and paths to all files in the directory
6 Call myfind with a path to a directory containing a subdirectory It should recursively print the directories' paths and their contents
7 Call myfind with . It should print . and all its contents
8 Call myfind with .. It should print .. and all its contents
9 Call myfind with -l on a single file It should print the file path and number of lines in the file
10 Call myfind with -l on a directory containing nested files and directories It should recursively print the directory and contents with lines for regular files

9. Grading schema

Criterion Points
The git repo exists 1
The program is written, builds, and runs as described here 1
Tests pass, prorated by the number of test cases passing 6
TOTAL 8

Author: Paul Gazzillo

Created: 2025-09-30 Tue 13:53

Validate