22

I have a bash script that recieves a set of files from the user. These files are sometimes under directories with spaces in their names. Unfortunately unlike this question all the filenames are passed via the command line interface. Let's assume the paths are correctly quoted as they are passed in by the user, so spaces (save for quoted spaces) are delimiters between paths. How would I forward these parameters to a subroutine within my bash script in a way that preserves the quoted spaces?

Community
  • 1
  • 1
fbrereto
  • 35,429
  • 19
  • 126
  • 178

4 Answers4

27
#! /bin/bash

for fname in "$@"; do
  process-one-file-at-a-time "$fname"
done

Note the excessive use of quotes. It's all necessary.

Passing all the arguments to another program is even simpler:

process-all-together "$@"

The tricky case is when you want to split the arguments in half. That requires a lot more code in a simple POSIX shell. But maybe the Bash has some special features.

Roland Illig
  • 40,703
  • 10
  • 88
  • 121
  • Thanks; what if I need to process them in bulk? – fbrereto Sep 23 '11 at 23:05
  • 1
    Also, make sure the subroutine properly double-quotes everything, e.g. `process-one-file-at-a-time() { cp "$1" "backupdir/$(basename "$1")"; }` – Gordon Davisson Sep 24 '11 at 02:45
  • 4
    You can save an incredible eight characters by removing the "`in "$@"`" part - It loops over the parameters by default. – l0b0 Sep 29 '11 at 08:14
  • For some reason I like the `in "$@"`, even though it is redundant. Maybe it's the melody and perceived grammar of the code when I read it aloud to myself. In other situations I do prefer code that is as brief as possible while still understandable, but somehow, this is not one of those situations. – Roland Illig Jul 08 '22 at 22:37
6

You want "$@", which has the special syntax of expanding $@ but preserving the white-space quoting of the caller (it does not create a single giant string with all the arguments in it). So someone can call your script like:

bash-script.sh AFile "Another File With Spaces"

Then in your script you can do things like:

for f in "$@"; do 
  echo "$f"; 
done

and get two lines of output (not 5).

Read the paragraph about the Special Parameter "@" here: http://www.gnu.org/s/bash/manual/bash.html#Special-Parameters

P.T.
  • 24,557
  • 7
  • 64
  • 95
0

Bravo @Roland . Thans a lot for your solution

It has really worked!

I wrote a simple script function that opens a given path with nautilus.

And I've just nested a function with this "helper"-for-loop into the main function:

fmp ()  {

    fmp2() { 
        nautilus "$@"; 
    };

    for fname in "$@";
    do         
        fmp2 "$fname";         
    done; 
}

Now I'm able to make all my scripts work handling with paths just by turning them into nested functions wrapped by a function with this helper-for-loop.

Sedat Kilinc
  • 2,843
  • 1
  • 22
  • 20
-1
"$var"

For example,

$ var='foo bar'

$ perl -E'say "<<$_>>" for @ARGV' $var
<<foo>>
<<bar>>

$ perl -E'say "<<$_>>" for @ARGV' "$var"
<<foo bar>>
ikegami
  • 367,544
  • 15
  • 269
  • 518