3

I am writing a script to delete all files in a directory for practice. I am using quotes around my variables, and yet I am still getting the following error:

/usr/local/bin/deleteall: line 6: [: too many arguments
/usr/local/bin/deleteall: line 11: [: too many arguments 

Here is my code:

#!/bin/bash
#Deletes all files in the current directory

read -p "You are about to delete all files in $(pwd). Are you sure you want to do this? y/n" yn
echo $yn
if [ [ "$yn" = "y" ] -o [ "$yn" = "Y" ] ] ; then
        for i in `ls`; do
                rm $i
        done
        exit;
elif [ [ "$yn" = "n" ] -o [ "$yn" = "N" ] ] ; then
        exit;
else
        read -p "Please enter y (yes) or n (no)"
        exit;
fi

And this is the entire output:

You are about to delete all files in <my dir>. Are you sure you want to do this? y/nn
n
/usr/local/bin/deleteall: line 6: [: too many arguments
/usr/local/bin/deleteall: line 11: [: too many arguments
Please enter y (yes) or n (no)n

What am I doing wrong?

William Oliver
  • 1,412
  • 4
  • 24
  • 35

3 Answers3

5

This line appears to be problem:

if [ [ "$yn" = "y" ] -o [ "$yn" = "Y" ] ] ; then

You can replace this with:

if [[ "$yn" == [yY] ]]; then

PS: Do same for the line where you check n or N.

anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 2
    @WilliamOliver: Because your syntax was incorrect. It should have been: `[ "$yn" = 'y' -o "$yn" = 'Y' ]` – anubhava Jan 21 '14 at 09:49
  • @mrjink Not in Bash conditionals – William Oliver Jan 21 '14 at 09:55
  • 1
    @WilliamOliver: No that's not true. You can use `[[ and ]]` wherever you've used `[ and ]`. `[` is actually a separate binary and `[[` is BASH's internal construct so performance wise `[[ and ]]` will be better. – anubhava Jan 21 '14 at 10:09
  • 2
    More specifically, `[` is a command name, not syntax for grouping, so you cannot just nest them like you attempted. – chepner Jan 21 '14 at 14:32
2

You can't nest []. It's literally interpreting the nested brackets as arguments, and printing an error that you have too many.

Just this will work

if [ "$yn" = "y" -o "$yn" = "Y" ]; then

Another alternate syntax using double brackets and same logic

if [[ $yn == "y" || $yn == "Y" ]]; then 

Also

for i in `ls`; do
  rm $i
done

Should really be

for i in *; do
  [ -f "$i" ] && rm $i
done

So it only tries to remove regular files (you will get errors for dirs, unless you overwrote rm, and you can decide what you want to do with symlinks). And ls is simply extraneous.

Reinstate Monica Please
  • 11,123
  • 3
  • 27
  • 48
  • is there a way to do nested conditionals in Bash? – William Oliver Jan 21 '14 at 10:00
  • 1
    @WilliamOliver Not as far as I know, but I can't think of a case where that would be a problem. Just use and/or and their respective symbols, or nest if blocks with conditions. – Reinstate Monica Please Jan 21 '14 at 10:03
  • 1
    "Nested conditionals" doesn't really make sense. I think you're looking for grouping, which can be done with parentheses: `if [[ ( "$yn" = "y" ) || ( "$yn" = "Y" ) ]]; then`. However, because `[` is a regular command, if you use that instead of `[[`, you must escape the parentheses: `if [ \( "$yn" = "y" \) -o \( "$yn" = "Y" \) ]; then`. – Gordon Davisson Jan 21 '14 at 15:48
0

this is what you want:

read -p "Are you sure? " -n 1 -r
echo    # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
     for i in `ls`; do
      rm -rf $i
done
fi

if [[ $REPLY =~ ^[Nn]$ ]]
then
     #do what you want
done
fi
MLSC
  • 5,872
  • 8
  • 55
  • 89