1

I am very new to bash scripting first and foremost. I wrote a script that checks for entries inside of a directory and prints information about the entries. If the entries are files it prints the file size and if there are directories it prints how many items are in those directories. When I run the script against the directory it is located in the script completes successfully. If I run the script against another directory I receive the error "Binary operator expected". Is this to be expected? Here is the code:

#!/bin/bash
# Print the contents of a directory with details on files and directories

files=( $1* )
count=0
for entry in $1/*
do
    if [ -d $entry ]
    then
        for f in $entry/*
            do
                let count=count+1
            done
        echo $entry ":" "This is a directory with $count files present."
        let count=0
    else [ -f $entry ]
        echo $entry "This is a file of" $(wc -c <"$entry") "bytes."
    fi
done

I'm sure this code isn't perfect and most likely has an easier method so I am just looking for some advice. Thank you for any help.

FurmanTheGerman

12
  • 1
    How do you run against another directory? What is your current directory at the time? Commented Apr 8, 2020 at 19:57
  • 4
    Hey @FurmanTheGerman First, always quote your variables (e.g. "$entry" and "$1") Second, proceed step by step and use #!/bin/bash -v or #!/bin/bash -x to see what's going on. Commented Apr 8, 2020 at 20:02
  • I think I may have made it work and I also realized the code I placed had $(ls) which was supposed to say $1/*. Thanks for the comments gildux I will do that. Commented Apr 8, 2020 at 20:06
  • The command line I am running looks like ./script.sh ~/Downloads @PM 77-1. Commented Apr 8, 2020 at 20:09
  • 2
    Filenames and Pathnames in Shell: How to do it Correctly Commented Apr 8, 2020 at 20:43

1 Answer 1

1

Fixed script:

#!/usr/bin/env sh

for entry in "$1/"*; do
  if [ -d "$entry" ]; then
    count="$(printf '%s\0' "$entry/"* | grep -cF '')"
    printf '%s : This is a directory with %d files present.\n' "$entry" "$count"
  else
    if [ -f "$entry" ]; then
      size="$(wc -c <"$entry")"
      printf '%s This is a file of %d bytes.\n' "$entry" "$size"
    fi
  fi
done
  • Removed unused assignment with missing quotes around the $1 argument:
    files=( $1* )
  • Fixed missing quotes around the $entry variable:
    if [ -d $entry ]
  • Replaced loop with single assignment, broken indentation and missing quotes around the non-globbing part of the path $entry/:

        for f in $entry/*
            do
                let count=count+1
            done
    
  • Replaced echo mixing literal and variables with missing quotes by a proper printf: echo $entry ":" "This is a directory with $count files present." echo $entry "This is a file of" $(wc -c <"$entry") "bytes."
  • Added missing quotes around the $entry variable and added missing if block: else [ -f $entry ]

Explanations about counting the entries in the directory without running a shell loop:

printf '%1s\0' "$entry/"* | grep -cF '':

  • printf '%1s\0' "$entry/"*: Prints a null delimited list of all files.
  • | grep -cF '': Pipe it into grep to count the null characters (1 per entry)
Sign up to request clarification or add additional context in comments.

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.