Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Including more commands if CSV column is not empty

Let's say I have the following CSV file (sample.csv)

filepath1
filepath1,filepath2
filepath1,filepath2,filepath3
filepath1,filepath2,filepath3,filepath4
filepath1,filepath2

And the program I need to use uses the following syntax:

program_im_using --file filepath1

But if multiple files are present, the syntax for input is:

program_im_using --file filepath1 --file filepath2
or
program_im_using --file filepath1 --file filepath2 --file filepath3

What I would do to paste the values from the CSV file would be something like this:

filepath_first=( $(awk -F "\"*,\"*" '{print $1}' $sample_csv) )
filepath_second=( $(awk -F "\"*,\"*" '{print $2}' $sample_csv) )

for i in "${!filenames[@]}"; do
    program_im_using --file "${filepath_first[i]}" --file "${filepath_second[i]}"
done

My example of what I'm doing only works if I have exactly 2 columns of values in every row. How can I generalize in a way such that if I have one column, I get:

program_im_using --file filepath1

But if I have two

program_im_using --file filepath1 --file filepath2

etc?

like image 209
Gabriel G. Avatar asked Jan 22 '26 09:01

Gabriel G.


2 Answers

You can use xargs:

sed 's/,/ --file /g' file.csv | xargs -L1 program_im_using --file
like image 141
Diego Torres Milano Avatar answered Jan 24 '26 04:01

Diego Torres Milano


For a variable number of args one common approach is to store the args in an array, eg:

$ args=(--file filepath1 --file filepath2)
$ typeset -p args
declare -a args=([0]="--file" [1]="filepath1" [2]="--file" [3]="filepath2")

A sample script to list input args:

$ cat program_im_using
#!/bin/bash
n=1
for i in "$@"; do echo "arg #$n:$i:";((n++));  done

We can then feed these args to the program like such:

$ ./program_im_using "${args[@]}"
arg #1 :--file:
arg #2 :filepath1:
arg #3 :--file:
arg #4 :filepath2:

Sample input file:

$ cat sample.csv
filepath1
filepath1,filepath2
filepath1,filepath2,filepath3
/a/b/c.txt,/d/e/f/g.txt,/h.txt

Using sed to reformat our csv lines:

$ sed 's/^/--file /; s/,/ --file /g' sample.csv
--file filepath1
--file filepath1 --file filepath2
--file filepath1 --file filepath2 --file filepath3
--file /a/b/c.txt --file /d/e/f/g.txt --file /h.txt

Feeding the sed results to a bash/while-read loop:

while read -ra args
do
    printf "\n####### ${args[*]}\n"
    ./program_im_using "${args[@]}"
done < <(sed 's/^/--file /; s/,/ --file /g' sample.csv)

NOTES:

  • OP has stated in comments that we do not need to worry about spaces or special characters in the csv fields otherwise ...
  • this approach will fail if the csv fields contain (white)space or characters that have a special meaning to bash

This generates:

####### --file filepath1
arg #1 :--file:
arg #2 :filepath1:

####### --file filepath1 --file filepath2
arg #1 :--file:
arg #2 :filepath1:
arg #3 :--file:
arg #4 :filepath2:

####### --file filepath1 --file filepath2 --file filepath3
arg #1 :--file:
arg #2 :filepath1:
arg #3 :--file:
arg #4 :filepath2:
arg #5 :--file:
arg #6 :filepath3:

####### --file /a/b/c.txt --file /d/e/f/g.txt --file /h.txt
arg #1 :--file:
arg #2 :/a/b/c.txt:
arg #3 :--file:
arg #4 :/d/e/f/g.txt:
arg #5 :--file:
arg #6 :/h.txt:
like image 27
markp-fuso Avatar answered Jan 24 '26 05:01

markp-fuso



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!