chindit
chindit

Reputation: 1009

Transfer a path with space in bash

I'm trying to run a program on every file on a dir. But there is spaces in the name of the file. For example, a file can be named «/my/good/path/MY - AWFUL, FILE.DOC» And when I'm trying to send the path to my the other tool (a python script), I've got an error saying «MY» is not a existing file. :(

Here is my current bash code:

#!/usr/bin/bash

for file in $(find "/my/pash" -name "*.DOC")
do
    newvar=`program "$file"`
done

So… where is my problem?

Thanks everyone :)

Upvotes: 0

Views: 100

Answers (5)

dinox0r
dinox0r

Reputation: 16059

That is because the for loop will take every word inside the result of the find as an element to iterate over. for will see it as:

for file in {/my/good/path/MY, -, AWFUL, FILE.DOC}
    echo "$file"
done

And will print:

/my/good/path/MY
-
AWFUL,
FILE.DOC

One solution to this problem is to use the xargs program to pass the result of the find as your python program argument:

find "/my/pash" -name "*.DOC" -print0 | xargs -0 -i program "{}"

Upvotes: 1

glenn jackman
glenn jackman

Reputation: 247210

Some correct answers, but no explanations so far:

a for loop is intended to iterate over words not lines. The given (unquoted) string is subject to word splitting (which is what is troubling you) and filename expansion, and then you iterate over the resulting words. You could set IFS to contain only a newline. The safest way is to use find -print0 and xargs -0 as demonstrated by Vytenis's answer

Upvotes: 2

Tim Pote
Tim Pote

Reputation: 28059

#!/usr/bin/bash

find "/my/pash" -name "*.DOC" | while read file; do
  newvar="$(program "$file")"
done

Note that this only fixes the case where a space or tab is in the file name. If you have a newline in the file name, it gets a little more complicated.

Upvotes: 1

Vytenis Bivainis
Vytenis Bivainis

Reputation: 2366

find -name "*.DOC" -print0 | xargs -r -0 -n1 program

Upvotes: 1

leu
leu

Reputation: 2081

the loop treats blanks as delimiter, so try this one:

find "/my/pash" -name "*.DOC" | while read file; do 
   newvar=`program "$file"`
done

Upvotes: 0

Related Questions