Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm writing a shell script that contains a command that takes multiple directories as space-separated input arguments (like ls). I would like to fill in those arguments from a variable but don't know how to ensure words like "for" aren't interpreted as arguments. Here's an example that expresses my idea:

#!/bin/bash

dirs="
 $HOME/Documents
 $HOME/Music
"

ls \
for dir in $dirs
do
    "$dir "
done
share|improve this question

1 Answer 1

up vote 4 down vote accepted

In:

dirs="
  $HOME/Documents
  $HOME/Music
"

You're assigning a string (containing spaces and newline characters and whatever characters $HOME may contain) to a scalar variable ($dirs).

Then, you want to pass a list of directories to ls, that is several arguments. So you need somehow to split that string into a list of arguments to pass to ls. How are you going to split it? On spaces and newlines? What if $HOME contains spaces or newlines?

POSIX shells do have a splitting operator, actually they have a split+glob operator which you invoke by leaving a variable unquoted. Luckily enough, by default, the splitting is done on space and newline (and tab). So you could do:

IFS=' ''
' # space and newline
set -f # disable globbing as we want only the
       # splitting part of the split+glob operator
ls -- $dirs

But here, since we want a list, best would be to store the elements into a list-type variable instead of joining them into a string only to split it later.

POSIX shells have the array of positional parameters ($1, $2...) for that:

#! /bin/sh -
set -- ~/Documents ~/Music
ls -- "$@"

Or if you don't mind making your script slower and less portable, use a shell with array variables like bash:

#! /bin/bash -
files=(
  ~/Documents
  ~/Music
)
ls -- "${files[@]}"

Or zsh:

#! /bin/zsh -
files=(
  ~/Documents
  ~/Music
)
ls -- $files
share|improve this answer
    
May have misunderstood OP, but: given $dirs as set by OP, why not just ls -- $dirs (variable not quoted)? –  grebneke Mar 2 at 20:46
1  
@grebneke, because that stops working when the filenames contain blanks or wildcard characters or start with -. If you want to store several things, you want arrays. If you use a scalar variable, then you need to start making assumptions. –  Stéphane Chazelas Mar 2 at 20:48
    
Right. I was assuming the example given in the question which seems straight forward. Thanks. –  grebneke Mar 2 at 20:49
1  
@grebneke, even in this case, we don't know what $HOME contains. My HOME directory is /All Volumes/v*/Stephane Chazelas –  Stéphane Chazelas Mar 2 at 20:58
1  
@Cerran - and note the double quotes: "${array[@]}"! –  grebneke Mar 3 at 20:32

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.