1

I'm trying to to write a bash script to automate the installation of my packages. So the idea is to read a .csv file (packages.csv) like this one:

pkg,Description,option
wget,file downloader,on
curl,tool to transfer data from or to a server,on
nano,text editor for Unix-like computing systems,off
emacs,An extensible customizable free/libre text editor — and more,on

build an array for each column (without header) and then pass the arrays to a dialog checklist.

#!/bin/bash

input="packages.csv"
while IFS=',' read -r col1 col2 col3
do 
    for a in $col1; do
        array_col1+=("$a") 
    done

    for b in $col2; do
        array_col2+=("$b")
    done

    for c in $col3; do
        array_col3+=("$c")
    done        

done < "$input"

array1=("${array_col1[@]:1}")
array2=("${array_col2[@]:1}")
array3=("${array_col3[@]:1}")

let num=${#array2[*]}-1

for i in $(seq 0 $num); do
    list[i]=$(echo ${array1[i]} ${array2[i]} ${array3[i]})
done

OPTION=$(dialog --checklist "Choose packages:" \
10 60 4 \
${list[*]})
exitstatus=$?
if [ $exitstatus = 0 ]; then
    echo "$OPTION"
else
    echo "Cancel"
fi

I did get it working at some point but without any spaces in the description. After I did some changes in order to include the spaces it doesn't work at all. How can I fix it? Actually in my .csv file I have more than 3 columns but bash checklist expects 3 arguments. Is it possible to somehow include them in the checklist?

5
  • Have you considered using something like puppet instead? The link has an example of your exact use case.
    – hhoke1
    Apr 20, 2018 at 15:27
  • No, puppet seems to be an overkill for this simple case. Apr 20, 2018 at 15:38
  • What is for a in $col1; do for? And the same for b and c? I think when you do it for b, $col2 undergoes word splitting with standard IFS; then you get multiple b-s while still parsing a single line. Apr 20, 2018 at 17:08
  • @Kamil Maciorowski: Fill the 3 arrays Apr 20, 2018 at 17:12
  • I have found this here: stackoverflow.com/questions/30146241/… which works. The middle argument is within single quotes and left and right arguments are not. This must be the problem but I don't know how to fix it... Apr 20, 2018 at 17:21

1 Answer 1

2
#!/bin/bash

input="packages.csv"
while IFS=',' read -r col1 col2 col3 dummy
do
   array+=("$col1")
   array+=("$col2")
   array+=("$col3")
done < <(tail -n +2 "$input")

option=$(dialog --checklist --output-fd 1 "Choose packages:" 10 60 4 "${array[@]}")

exitstatus=$?
if [ $exitstatus = 0 ]; then
    echo "$option"
else
    echo "Cancel"
fi

Main changes:

  • tail -n +2 "$input" to strip the header;
  • dummy variable to allow more than three columns (extra columns don't matter to dialog);
  • one array variable to build input for dialog instead of many that pass data in a crippled way;
  • "${array[@]}" as a proper way to pass array as command line arguments in this case;
  • --output-fd 1 explained in this answer (there are better, more robust solutions there);
  • lowercase variables per this answer.

Actually in my .csv file I have more than 3 columns but bash checklist expects 3 arguments. Is it possible to somehow include them in the checklist?

What for? True, dialog --checklist expects them three by three. Keep it tidy. I guess maybe you need more columns for your code that comes after dialog. Consider this: when dialog successfully returns identifiers from the first column and you have them in $option, parse its output like this:

for package in $option; do … ; done

(For this to work your first column in packages.csv cannot contain spaces etc.)

This way you can do something for every chosen package. Inside this loop you can read as many columns as you need anew, but first grep for the proper line:

IFS=',' read -r col1 col2 col3 col4 col5 col6 dummy < <(grep "^${package}," "$input")

(Hint: investigate read -a, see help read). And then, still inside the loop, do the rest of your job.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .