sharat87
sharat87

Reputation: 7526

Send each line as a single argument in bash

I have a variable in bash, which is something like

filenames='file 1
file 2
file 3'

I need to send each line in the above variable's content as a single argument to a program. But I can't get bash to that. Here's what I tried:

python -c 'import sys; print sys.argv' $filenames
['-c', 'file', '1', 'file', '2', 'file', '3']

or

python -c 'import sys; print sys.argv' "$filenames"
['-c', 'file 1\nfile 2\nfile 3']

What I'm expecting is something like this

['-c', 'file 1', 'file 2', 'file 3']

I've tried fiddling with the IFS setting too, but couldn't get it right. Any ideas on this?

Upvotes: 1

Views: 345

Answers (5)

bhdnx
bhdnx

Reputation: 530

What about xargs:

$ seq 10 | xargs  python -c 'print __import__("sys").argv'
['-c', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']

Upvotes: 0

tripleee
tripleee

Reputation: 189397

Just to add another option,

OLDIFS=$IFS
IFS='
'
set -- $filenames
python -c 'import sys; print sys.argv; print sys.stdin.readlines()' "$@"
IFS=$OLDIFS

Edit: Add code to save old value in OLDIFS and restore it afterwards. IFS='whatever' set -- $var on a single line does not work.

Upvotes: 1

Huang F. Lei
Huang F. Lei

Reputation: 1865

Yet another option:

while read line ; do
  python -c 'import sys; print sys.argv' $line;
done <(echo $filenames)

Upvotes: 0

Gordon Davisson
Gordon Davisson

Reputation: 125798

Double-evaluating a command with either eval or sh -c can lead to weird bugs if you don't get the extra level of quoting just right. I'd recommend using an array instead, either just by storing the file list as an array to begin with:

filearray=("file 1" "file 2" "file 3")
python -c 'import sys; print sys.argv' "${filearray[@]}"

or by converting it from newline-delimited string to an array:

filenames='file 1
file 2
file 3'
oldIFS="$IFS"; IFS=$'\n'
filearray=($filenames)
IFS="$oldIFS"
python -c 'import sys; print sys.argv' "${filearray[@]}"

Upvotes: 2

perelman
perelman

Reputation: 1777

$ export filenames="file 1
file 2
file 3"
$ echo "$filenames" | xargs -d\\n python -c 'import sys; print sys.argv'
['-c', 'file 1', 'file 2', 'file 3']

Another way using read instead of xargs:

#!/bin/bash
filenames="file 1
file 2
file 3"
cmd="python -c 'import sys; print sys.argv; print sys.stdin.readlines()'"
while read file
do
    args="$args \"$file\""
done < <(echo "$filenames")
echo $cmd $args
echo `echo hi | sh -c "$cmd $args"`

Output:

$ ./test.sh 
python -c 'import sys; print sys.argv; print sys.stdin.readlines()' "file 1" "file 2" "file 3"
['-c', 'file 1', 'file 2', 'file 3'] ['hi\n']

Upvotes: 2

Related Questions