1

I'm writing a shell script that is supposed to take in one parameter (a directory name) and display how many files, directories, readable files, writable files and executable files are in that directory. If a parameter isn't given when you run it, its supposed to display an error message and abort. If the given parameter doesn't exist it should also display an error message and abort. Otherwise it should display the above info. I cannot for the life of me get it to run. Here is what I have, please help!:

   #!/bin/csh
   $1
   set file=$1
       if ($file==0)then
             echo "usage: assignment6.sh <directory_name>"
             exit0
       else
           if (-e $file && -r $file) then
                echo "Number of Directories: `ls | wc -w`"
                echo "Number of Files: `ls -d */ | wc -w`"
                echo "Number of Readable files: `find * -type f -or -type d -maxdepth 0 -perm +u=r | wc -w`"
                echo "Number of Writable files: `find * -type f -or -type d -maxdepth 0 -perm +u=w | wc -w`"
                echo "Number of Executable files: `find * -type f -or -type d -maxdepth 0 -perm +u=x | wc -w`"

            else
                if (! -e $file) echo "No such directory."
                exit 0
            endif
       endif
 exit 0
  • In what language is that script written? – AlexP Nov 18 '16 at 21:42
  • yeah it's bash. – Maddie Nov 18 '16 at 21:50
  • Sorry, mind block. It's csh. In my defense I was never a fan of csh and I haven't used it in the last 20 years... – AlexP Nov 18 '16 at 21:50
  • 1
    No it's not bash, it's csh. In bash the if construct is if condition ; then then-part else else-part fi. In csh it is like you wrote, if (condition) then then-part else else-part endif. In bash assignment is plain variable=value -- set is from csh. – AlexP Nov 18 '16 at 21:52
  • @Maddie, if this is csh you should add the proper shebang to the top of your script #!/bin/csh – Zachary Brady Nov 18 '16 at 21:54
2

Issues in this script:

  1. You are parsing the output of ls. Don't parse ls.
  2. You are relying on filenames not to contain spaces or newlines. They can contain either.
  3. You're using csh. All by itself, that's a bad idea for shell scripts. Bash, Ksh, Zsh, almost anything but csh is a better idea. (My opinion, but read through the linked factual reasoning.)

Here is a POSIX compliant version of part of this program. (If I have time later I may include the rest of the features.)

This won't handle cases where there are more files than fit in an argument list, but it could be modified to do so if really necessary.

#!/bin/sh

[ "$#" -eq 1 ] && [ -d "$1" ] || {
  printf 'Usage:\t%s <directory>\n' "$0"
  exit 1
}

dirs="$(find "$1" -path '*/*/*' -prune -o -type d -exec sh -c 'printf %s\\n "$#"' sh {} +)"
files="$(find "$1" -path '*/*/*' -prune -o -type f -exec sh -c 'printf %s\\n "$#"' sh {} +)"

printf 'Number of directories in %s:\t%s\n' "$1" "$dirs"
printf 'Number of files in %s:\t%s\n' "$1" "$files"

Since the -maxdepth primary is not portable, I made use of the techniques described here:

  • Actually this will report one directory too many, as it reports itself. Unfortunately I don't have time to work on it further at this moment. – Wildcard Nov 18 '16 at 22:51
  • Also, unless I'm misunderstanding, it will fail if there are so many files / directories, or their names are so long, that they cannot be passed on a single command line. But +1 for everything else. – G-Man Nov 18 '16 at 23:51
  • @G-Man, correct; I mentioned that actually. Feel free to make an edit if you think that wasn't made clear enough. – Wildcard Nov 18 '16 at 23:58
  • @G-Man, I haven't made the necessary huge number of files to test, but I believe all that would be necessary to handle vast numbers of files would be dirs="$(printf %s "$dirs" | tr '\n' + | bc)". Right? – Wildcard Nov 19 '16 at 0:01
  • 1
    Sorry; it's clear enough.  I read it too quickly and skidded over that paragraph. … … … I can't get your answer to work; I believe that you need (printf "%s" "$dirs" | tr '\n' +; echo) | bc.  Or (much as I hate to use unquoted variables), echo $dirs | tr " " + | bc. – G-Man Nov 19 '16 at 0:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.