0

I'm working on a script that downloads things.

In the script I need to correlate a name and a URL that will be downloaded repeatedly (hence the script)

name1,url1
name2,url2
name3,url3


command $NAME $URL

So I want a for each loop that goes through my list of names and respective urls. What's the best way to accomplish this? Not interested at this time in keeping those lists in an external file or anything. In the script is where I would like it for this example.

  • Is the name somehow significant? If it's a filename, why not just have that be part of the URL? – DopeGhoti Jan 11 '17 at 21:00
  • The name is significant. Yes. It becomes part of a directory structure. – LVLAaron Jan 11 '17 at 21:08
3

bash is quite limited on that front. You may want to try other shells.

With zsh (you're already using zsh syntax as you didn't quote your variables in command $NAME $URL):

for name url (
  name1 url1
  name2 url2
  name3 url3
) command $name $url

With bash or other POSIX shell, you could do:

while IFS=, read <&3 -r name url; do
  {
    command "$name" "$url"
  } 3<&-
done 3<< "EOF"
name1,url1
name2,url2
name3,url3
EOF

That means the values can't contain commas or newlines though.

Recent versions of bash also support associative arrays using a syntax looking more like that of ksh93 than of zsh. So if the names are unique, you could do:

typeset -A pairs
pairs=(
  [name1]=url1
  [name2]=url2
  [name3]=url3
)
for name in "${!pairs[@]}"; do
  url=${pairs[$name]}
  command "$name" "$url"
done

That would also work in ksh93. Beware the quoting rules vary slightly between both. In zsh, the associative array definition syntax is more straightforward and the normal quoting rules apply:

pairs=(name1 url1 name2 url2 name3 url3)

Which you can put on several lines:

pairs=(
  name1 url1
  name2 url2
  name3 url3
)

Beware the order is not preserved though and that bash associative arrays don't support an empty key.

ksh93 supports multi-dimensional arrays, so you could do:

pairs=((name1 url1) (name2 url2) (name3 url3))
for ((i = 0; i < ${#pairs[@]}; i++)); do
  name=${pairs[i][o]} url=${pairs[i][1]}
  command "$name" "$url"
done
1

You could create a here-document that's written to a temporary file and then processed. The temporary file will automatically be removed so no manual cleanup is required.

#!/bin/bash
mylist=/var/tmp/$$
trap 'rm -f ${mylist}' EXIT
cat << _EOF_ > ${mylist}
name1 url1
name2 url2
name3,url3
_EOF_
while read name url
do
    printf "%s %s\n" ${name} ${url}
done < ${mylist}
1

At beginning i drove my mind to something complicated like associative arrays.
Then i realized that can be done as easy as bellow, considering that you have as many names as urls:

root@debian:a=( "name1,url1" "name2,url2" "name3,url3" );while IFS="," \ 
read -r name url;do echo "command $name $url";done<<<$(printf '%s\n' "${a[@]}")
command name1 url1
command name2 url2
command name3 url3

All you need is to store names and urls in the same array (a in my test) together, separated i.e by comma.

0

Maybe a plain bash script will work for you:

pairs=( "name1,url1" "name2,url2" "name3,url3" )

for pair in "${pairs[@]}"; do
    IFS=, read name url <<<"${pair}"
    printf "%s %s\n" "${name}" "${url}"
    command "${name}" "${url}"
done
0

A bit overly complex in it's own right but sticking with the format that most others have given, but not invoking IFS I'd use

pairs=( "name1,url1" "name2,url2" "name3,url3" )

for pair in "${pairs[@]}"; do
    #Create an array in itself, of the two values.
    tmpArr=(`echo $pair | tr ',' ' '`)

    #Then either use Array Indexing on the array ie. 
    #Or place the offsets in their own variables. ie Run=${tmpArr[0] ...;
    command ${tmpArr[0]} ${tmpArr[1]}
done

Eliminates the need for Temporary Files, no real cleanup needed, as long as used within a script which Sha-Bangs initially, or made local in a function, which is the way I've done most of my scripting, keeping syntax as close to 'C' as possible. Sticks to my bash motto as well, "If you want to do it, someone's done it before, and made it a module, so don't do the work over..."

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.