0

This is one of my homework exercise.

 Write a shell program, which will take a directory as an argument. 
The script should then print all the regular files in the directory and all 
the recursive directories, with the following information n the given order for 
each of the files 

File name (full name from the specified directory)     file size    owner 

In case the directory argument is not given, the script should assume the 
directory to be the current working directory 

I am confused about how to approach this problem. For the listing of files part, I tried

ls -R | awk ...
but i was not able to do it because I was not able to find a suitable field seperator for awk. I know its unfair to ask for a solution, but please can you guys give me a hint as how to proceed with the problem? Thanks in advance.

4 Answers 4

3

You really don't want to use ls and awk for this. Instead you want to check the documentation for find to figure out what string to put in the following script:

find ${1:-.} -type f -printf "format-string-to-be-determined-by-reader\n"
Sign up to request clarification or add additional context in comments.

1 Comment

No --exec. The --printf option to find (gnu find 4.1.20, possibly others) gives you everything you need.
2

The problem is that parsing the output of ls is complicated at best and dangerous at worst.

What you'll want to do is use find to produce the list of files and a small shell script to produce the output you want. While there are many possible methods to accomplish this I would use the following general form

while read -r file ; do
    # retrieve information about $file
    # print that information on one line
done < <(find ...)

With a suitable find command to select the files. To retrieve the metadata about the files I would use stat inside the loop, probably multiple times.

I hope that's enough of a hint, but If you want a complete answer I can provide.

2 Comments

Thank you @Sorpigal. I tried executing a very simple version of yours, with a echo hi in between while and done. while read -r file ; do echo "hi" done << (find .) I am getting error as "( unexpected" in line 3
Whitespace is important. done < <(find .) is not the same as done << (find .).
0

awk is fine.. use " +" as separator.

2 Comments

When i gave ls -R, the full output is running into pages. When a new directory is found, a big line like ./blah/blah is appearing and again the pattern resorts to like that of ls -l. And correct me if am wrong. The output does not have any + sign? How to seperate with it
@CHID: FS takes a regexp. (In gawk, -F" " would be special-cased to do the same thing, apparently. Still, see above comments on not doing this with ls+awk)
0

Bah. Where's the challenge in using ls or find? May as well write a one-liner in perl to do all the work, and then just call the one-liner from a script. ;)

You can do your recursive directory traversal in the shell natively, and use stat to get the size and owner. Basically, you write a function to list the directory (for element in *), and have the function change to the directory and call itself if [[ -d $element ]] is true. Something like

do_print "$elem"
if [[ -d "$elem" ]]
then
  cd "$elem"
  process_dir
  cd ..
fi

or something akin to that.

Yeah, you'll have a zillion system calls to stat, but IMHO that's probably preferable to machine-parsing the output of a program whose output is intended to be human-readable. In this case, where performance is not an issue, it's worth it.

For bonus super happy fun times, change the value of IFS to a value which won't appear in a filename so the shell globbing won't get confused by files containing whitespace in its name. I'd suggest either a newline or a slash.

Or take the easy way out and just use find with printf. :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.