tags:

views:

28

answers:

3

Hi everyone,

below is an extract from a shell script i am tring to make, it is supposed to allow a user to supply files they want to view and the script prints the first lines of the each file and asks if they want to delete them. i have marked where the errors are, i know i am using the $ improperly.

any help would be appreciated thanks :)

count=1

while [ $# -ge $count ]

do
        head $"$count"//error here
    echo -e "Delete file $$count?? (y/n):"//error here

    read answer
    case $answer in
               Y|y)rm $"$count"//error here
                 echo -e "File $$count deleted\n" ;;//error here
               N|n)echo -e "File $$count NOT deleted\n" ;;//error here
               *)echo "Invalid Command";;
    esac            

    count=`expr $count + 1`
done
A: 

You can do it this way:

# loop till you have filenames
while [ $# -ge 1 ]
do
        # display the first 10 lines for 1st file.
        head $1

        echo -e "Delete file $1?? (y/n):"
        read answer

        case $answer in
        Y|y)rm $1
        echo -e "File $1 deleted\n" ;;

        N|n)echo -e "File $1 NOT deleted\n" ;;
        *)echo "Invalid Command";;

        esac            

        # shift the parameters.
        # you loose 1st argument, 2nd argument becomes 1st
        # $# is decremented.                                                                                                                                                                                   
        shift
done
codaddict
Thanks for the suggestion but the user can supply multiple files to view, hence why I have a loop. Thanks again for the reply though :)
mrblippy
@mrblippy: In this case user can supply any number of filenames on the command line.
codaddict
ok thanks very much
mrblippy
+1  A: 

Using positional parameters in this case is silly, because you do not care about the position; only about its actual value. Use bash's $@ array:

for file in "$@"; do
    head "$file";
    read -p "Delete file \"$file\"? (Y/N) " answer;
    case "$answer" in
        Y|y) rm -v "$file";;
        N|n) echo "File \"$file\" was not deleted.";;
        *) echo 'Invalid command';;
    esac;
done;
  • Used "$@" instead of messing about with $1 and shift.
  • Quoted parameters when using them in commands.
  • Specified a prompt for read instead of first echoing it.
janmoesen
so there is no way i can do it with propositional parameters???
mrblippy
Sure there is, but it is silly. Change the first line to: `while [ $# -gt 0 ]; do` and add `file="$1"; shift;` between the first line and the one with `head`.
janmoesen
A: 

What you seem to be trying to do is called "indirection". You can use it to access the positional parameters, but using shift or using for file as in janmoesen's answer would be preferable.

Here's how indirection would work:

#!/bin/bash
count=1
while (( count <= $# ))
do
    echo "${!count}"
    ((count++))
done

You would use ${!count} in the places you have "$$count" in your script.

By the way, as you can see in my example, it's not necessary to use expr to increment your variable.

Dennis Williamson