Specifying a list name as argument and using that list in script.

Is there a way I can specify the name of a list as an argument to a shell script and then use the values of that list name in the script?
I need to do this WITHOUT using case statements.

Something like this:

check.sh list1
#!/bin/bash

list1="www.amazon.com www.google.com"
list2="www.redhat.com www.apple.com"
list3="www.amazon.com www.apple.com"

for H in $1; 
   do ping -c 1 $H;	# Doesn't work
done;

My reason for not wanting to use case statements is that the lists will be added/changed/removed by other Sys Admins and I don't want all of us to be mucking around with the script. Actually the lists will be in a different file altogether and I'll just source that file to make it even less likely the script will need to be opened.

If there's not a method in shell, can Perl handle this?

Thanks,
Gary

Changed it slightly to separate the items in the line.

while read line
do
    for H in $(echo $line | tr -d '"' | tr ' ' '\n')
    do
        echo $H
        ping -c 1 $H
        echo
    done
done < $1

The above should work for list files of any name or size with one item per line,
or many items per line (space seperated, quoted or unquoted).

Guess he ment more something like:

Untested:

#!/bin/bash
[[ -z "$1" ]] && echo "You passed no arguments!" && exit 1
SEARCH="$1"
oIFS="$IFS"
IFS="= \""
FILE_LIST="$HOME/list.txt"

grep ^$SEARCH "$FILE_LIST"|while read var entries;do
	for entry in $entries;do
		echo "Pinging $entry"
		ping -c1 "$entry"
	done
done

While the $HOME/list.txt contains:

list1="www.amazon.com www.google.com"
list2="www.redhat.com www.apple.com"
list3="www.amazon.com www.apple.com"

Hope this helps

EDIT (tested):
Forgot to add the quotes to IFS

Yes. It's called indirect referencing.

#!/bin/bash

list1="www.fsf.org www.defectivebydesign.org"
list2="www.gnu.org www.bash-hackers.org"
list3="www.linux-libre.fsfla.org www.stallman.org"

ref=$1

for H in ${!ref}
   do ping -c 1 $H
done
4 Likes

@ sea

Could you post your output please. Your script isn't working for me?
$ check.sh list1
---------- Post updated at 06:40 PM ---------- Previous update was at 06:17 PM ----------

@ junior-helper

I didn't know about ref . Thanks

When I run your script, it uses the list1 variable list1="www.fsf.org www.defectivebydesign.org" , not the command line argument.
$ check.sh list1
If I comment out the list1 variable in your script and run it, there is no output?

1 Like

You're welcome! The name of the reference variable doesn't have to be ref though.

Of course it uses the command line argument, otherwise it would not show the content of the list1 variable.

$1 is the first command line argument
ref=$1 command line argument is assigned to the ref variable
${!ref} accessing $list1 via $ref.

There is no error checking at all.
If you comment out list1 and use list1 as argument, the script fails to find the list1 variable, thus there is no output. It's the same as if you try check.sh list4 or even just check.sh .
Another issue you might come across is that the script will ignore potential arguments after the first argument, e.g. check.sh list1 list3 , I think you know why.

Hope this helps.

2 Likes

OK
I understand how it works now.

Thanks again.

/*
EDIT:
@ Junior-Helper: very nice one, thank you!
*/

For Ongoto:
(I just inserted linebreaks for readability)

 ~ $ cat testscript.sh list.txt ; sh testscript.sh list1

#!/bin/bash
[[ -z "$1" ]] && echo "You passed no arguments!" && exit 1
SEARCH="$1"
oIFS="$IFS"
IFS="\"= "
FILE_LIST="$HOME/list.txt"

grep ^$SEARCH "$FILE_LIST"|while read var entries;do
	for entry in $entries;do
		echo "Pinging $entry"
		ping -c1 "$entry"
	done
done

list1="www.amazon.com www.google.com"
list2="www.redhat.com www.apple.com"
list3="www.amazon.com www.apple.com"

Pinging 
ping: unknown host 
Pinging www.amazon.com
PING www.amazon.com (176.32.98.166) 56(84) bytes of data.

--- www.amazon.com ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

Pinging www.google.com
PING www.google.com (173.194.35.19) 56(84) bytes of data.
64 bytes from mil01s16-in-f19.1e100.net (173.194.35.19): icmp_seq=1 ttl=56 time=26.8 ms

--- www.google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 26.844/26.844/26.844/0.000 ms
+ ~ $ 

That is on and with:

uname -a
Linux $(hostname) 3.17.3-200.fc20.x86_64 #1 SMP Fri Nov 14 19:45:42 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
bash --version
GNU bash, Version 4.2.53(1)-release (x86_64-redhat-linux-gnu)
...

Hope this helps

1 Like

You guys are quick and very helpful! Thank you very much.
My original question was answered and I'll use something like below to start with. I'll incorporate the other suggestions to make my script better.

$ cat ping_names.txt 

LIST1="www.fsf.org www.google.com"
LIST2="www.redhat.com www.apple.com"
LIST3="www.fsf www.apple.com"
#!/bin/bash

source ./ping_names.txt

ref=$1

for H in ${!ref};  
   do ping -c 1 $H;     
done;
$ ./check.sh LIST1
PING www.fsf.org (208.118.235.131) 56(84) bytes of data.
64 bytes from www.fsf.org (208.118.235.131): icmp_req=1 ttl=52 time=84.8 ms

--- www.fsf.org ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 84.859/84.859/84.859/0.000 ms
PING www.google.com (74.125.25.147) 56(84) bytes of data.
64 bytes from pa-in-f147.1e100.net (74.125.25.147): icmp_req=1 ttl=47 time=19.6 ms

--- www.google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 19.685/19.685/19.685/0.000 ms

You don't need the ref=$1 . Try for H in ${!1};

1 Like