3

I want to download all files in this GitHub directory to /usr/share/enlightenment/data/config. I have this script:

L=('e.cfg' 'e_randr.cfg' 'exehist.cfg' 'module.battery.cfg' 'module.clock.cfg' 'module.conf.cfg' 'module.everything-apps.cfg' 'module.everything-files.cfg' 'module.everything.cfg' 'module.gadman.cfg' 'module.ibar.cfg' 'module.notification.cfg' 'module.pager.cfg' 'module.syscon.cfg' 'module.tasks.cfg')
pushd /usr/share/enlightenment/data/config
for i in $L
do
  sudo wget -c $JEF/$i #$JEF is defined in my ~/.bashrc script
done
popd

but it just downloads e.cfg and that is it.

2
  • Your code is correct zsh syntax, not in other shells. Nov 2 '15 at 10:44
  • 1
    I would avoid running wget as superuser. A few vulnerabilities have been found in wget in the past. Nov 2 '15 at 10:48
6

In bash or ksh, you need to iterate over all the elements of the array with:

for i in "${L[@]}"; do wget ....; done

${L[@]} will be expanded to all elements of the array L and for is used to iterate over those.

If you use $L is bash or ksh, it will behave as ${L[0]} i.e. in your case, you will get only the first element of the array.

1
  • 1
    +1. and don't forget to " quote $i as "$i" every time you use it.
    – cas
    Nov 2 '15 at 4:42
1

I figured out the answer, myself, by looking at Array variables in The Bash Beginners' Guide.

This is what the script should be:

L=('e.cfg' 'e_randr.cfg' 'exehist.cfg' 'module.battery.cfg' 'module.clock.cfg' 'module.conf.cfg' 'module.everything-apps.cfg' 'module.everything-files.cfg' 'module.everything.cfg' 'module.gadman.cfg' 'module.ibar.cfg' 'module.notification.cfg' 'module.pager.cfg' 'module.syscon.cfg' 'module.tasks.cfg')
pushd /usr/share/enlightenment/data/config
for i in ${L[*]}
do
  sudo wget -c $JEF/$i
done
popd
5
  • Don't use ${L[*]}, use ${L[@]} instead as my answer suggested..
    – heemayl
    Nov 2 '15 at 4:34
  • It worked though, why should I use ${L[@]} instead?
    – Josh Pinto
    Nov 2 '15 at 4:38
  • 1
    Yes, use ${L[@]}, and get into the habit of quoting!!! it: "${L[@]}"
    – user79743
    Nov 2 '15 at 9:02
  • Unquoted both ${L[*]}, and ${L[@]} work equivalently. When quoted, the * option joins each value with the first character of IFS (become one long value unless re-split), the @ option keeps each value separate.
    – user79743
    Nov 2 '15 at 9:15
  • 1
    Try L=(a b c d); printf "<%s>\n" "${L[*]}"; printf "<%s>\n" "${L[@]}". See the difference?
    – user79743
    Nov 2 '15 at 9:17
0

How about this? Fewer quotes, parethesis, and brackets, and other syntax!:

L='e.cfg e_randr.cfg exehist.cfg etc'

for i in $L
do
  echo wget -c "$JEF/$i" #$JEF is defined in my ~/.bashrc script
done

This is oldest and most common way to do it. More people understand this. Arrays are extensions that I have never used.

3
  • Missing the pushd and popd. Long lines should be avoided where possible.
    – user79743
    Nov 2 '15 at 9:06
  • It should be noted that It assumes IFS contains the space character and that none of the characters in those elements (and $JEF) appear in $IFS or are wildcard characters. Arrays were created to address those kind of issues. Nov 2 '15 at 10:46
  • @StéphaneChazelas Agreed. Good to know the caveats. In this case the elements are static strings. Isn't it extremely unlikely that this code would run without a space in IFS? I've scripted IFS=... but only in very controlled conditions, usually in a subshell. I've never seen it set globally or in the environment. Also agree, almost all variable references should be quoted, adding that.
    – RobertL
    Nov 2 '15 at 19:09

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.