This script should remove the contents of the dustbin directory. If the -a option is used the script should remove all files from the dustbin. Otherwise, the script should display the filenames in the dustbin one by one and ask the user for confirmation that they should be deleted.

if test ! -f ~/TAM/dustbin/*
  echo "this directory is empty"
  for resfile in ~/TAM/dustbin/* 
    if test -f $resfile ; then
      echo "Do you want to delete $resfile"
      echo "Y/N"
      read ans
      if test $ans = Y ; then 
        rm $resfile
        echo "File $resfile was deleted"

The above is working, however it causes a few errors to be reported even though it still carries out the code on the next line after the error without crashing.


./remove: line 4: test: to many arguments

(This happens when there are more than 2 files in the dustbin.)

./remove: line 4: test: root/TAM/dustbin/NewFile2: binary operator expected

(This happens when the file is newfile2 but not newfile3.)

Also does anyone have any input on how I could do the -a to delete everything in the folder without asking about each file separately?

  • 4
    What's wrong with rm -i -- ~/TAM/dustbin/*? – Stéphane Chazelas Nov 21 '12 at 12:44
  • 3
    Please quote your arguments. Otherwise, names with spaces will give you misery. if test -f "$resfile" ; then (etc). [This may actually be what you're seeing with two files, if you have spaces in the names] – derobert Nov 21 '12 at 17:02

Fro the first question, basically, you're giving too much parameters to the test there (it seems to me that the first line of what you've pasted is actually the 4th line of your script). If your case of multiple files, you will have test -f file1 file2 file3… while test would expect the binary operator (for example, "-a" for AND) after -f file1 and the next expression after that and so on.

As for supplying and processing the parameters for your script to automatically delete the files without asking for confirmation, you may use the same test on $1 (this will be your script's first command line parameter).


You have two main problems.

The first problem is what happens in the very first command: test ! -f ~/TAM/dustbin/*. First the shell expands the wildcard pattern ~/TAM/dustbin/*, then it passes the resulting list to the test command. That won't work if there is more than one matching file.

With any Bourne-style shell, you can save the list of matches in the positional parameters, and check whether the first word exists (if it doesn't, the pattern didn't match anything).

set ~/TAM/dustbin/*
if ! test -f "$1"; then
  echo "this directory is empty"

(See this answer for ways to make a non-matching glob pattern expand to an empty list in ksh, bash and zsh.)

Note that the directory may not be empty: it may contain dot files (files whose name begins with ., which the wildcard pattern * skips. If you want to check for the existence of dot files as well, the easiest portable way is to do it with find:

if [ "$(cd ~/TAM/dustbin && find . | head -n 1)" = "." ]; then
  echo "this directory is empty"
  set ~/TAM/dustbin/..?* ~/TAM/dustbin/.[!.]* ~/TAM/dustbin/*
  for x; do
    if [ -f "$x" ]; then
      # $x is a regular file
    elif [ -e "$x" ]; then
      # $x is a directory or other special file
      # $x is an unexpanded non-matching pattern

(Note that test -f only matches regular files; use -e to test whether a file exists.)

Another pervasive problem in your script is that you don't protect against file names containing shell special characters. Always use double quotes around variable substitutions "$foo" and command substitutions "$(foo)". Your script may choke or remove the wrong file if a file name contains whitespace or \[?*.

I assume this is a learning exercise. If it isn't:

setopt nullglob
rm -ri ~/TAM/dustbin/*

# check if the dir is empty
shopt -s nullglob
if (( ${#files[@]} == 0 )); then
    echo "the directory is empty"

# handle command line arguments
while getopts :a opt; do
    case $opt in
        a) all=true ;;
        ?) echo "unknown option: -$OPTARG"; exit 1 ;;
shift $((OPTIND - 1))

# perform the deletion
if $all; then
    command rm "$dir"/*
    command rm -i "$dir"/*

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.