tags:

views:

119

answers:

5

Is there any way to change the following string so I don't get any problems when there are files/folders with spaces in them?

files=`find ~/$folder -name "*@*" -type f`

I'd prefer if there was a solution that wouldn't have to involve having to change other parts of my code but this line of code, as everything seems to be working correctly, apart from this minor detail.

Thanks

EDIT: Here is the code in a bit more detail:

abc=( $(find "$pasta" -name "$ficheiro_original@*" -type f) )
abc_length=${#abc[@]}
+2  A: 

If you are not using those file names later in your script , just iterate them and process on the fly.

find ~/$folder -name "*@*" -type f | while read -r FILE
do
  echo "do you stuff"
done

otherwise, you can set IFS

IFS=$'\n'
files=$(find ~/$folder -name "*@*" -type f)

Update:

$ IFS=$'\n'
$ a=($(find . -type f ))
$ echo ${#a[@]}
14
ghostdog74
Edited the OP with some code.
devoured elysium
Setting IFS will have the problem that then abc_length will be 1, which is not desired.
devoured elysium
`IFS='$\n'` does not work for me, but `IFS=$'\012'` does.
Adam Backstrom
IFS='$\n' will work for me, but at the expense of having the rest of the code not working, as when I try to iterate over find's results, it will have all the results as just one string.
devoured elysium
My reproduction of your setup must be incomplete. Would need to see a complete failing sample including file and directory names for `find` to dig into, reduction of the problem script, and calling arguments (or bake those into the `find` call directly).
Adam Backstrom
The dollar sign goes outside the quotes: `$'\n'`
Dennis Williamson
+1  A: 

If you need a list of files that might have spaces in the names, you pretty much have to store them as an array, rather than just a string. Create the array with something like this:

saveIFS="$IFS"; IFS=$'\n'; files=( $(find ~/"$folder" -name "*@*" -type f) ); IFS="$saveIFS"

and then you'll have to modify the rest of the script to use files as an array rather than a string, and it (and other filenames) should always be in double-quotes to keep spaces from being mistaken as separators. For instance, anyplace you're currently using $files, replace that with "${files[@]}"

ls "${files[@]}"
for f in "${files[@]}"; do
    ls "$f"
done
echo "found ${#files[@]} files" 
Gordon Davisson
+1  A: 
Jonathan Leffler
`read -d ''` works for me.
Dennis Williamson
@Dennis: Without a null in it - OK; didn't think to try that...yup, it does seem to work; much neater than having nulls embedded in a script. I didn't see that stated in the documentation (bash reference manual) that I was looking at - which was a Bash 4.x version in PDF. Thanks!
Jonathan Leffler
+1  A: 

Here is another way to get around without changing the rest of code:

# files=($(find))
eval "files=($(find -printf '"%h/%f" '))"

for f in "${files[@]}"; do
  echo "$f"
done

It's dirty and will not work for filename with special characters, e.g. ". It uses eval to evaluate a string of a Bash array and -printf of find to form that string.

I personally prefer changing $IFS, just FYI.

livibetter
+1  A: 

To read file names with spaces into a Bash array variable, you could use the "read" builtin command as well:

printf '%q\n' "$IFS"

IFS=$'\n' read -r -d "" -a abc <<< "$(find ~/$folder -name "*@*" -type f)"
IFS=$'\n' read -r -d "" -a abc < <(find ~/$folder -name "*@*" -type f)  # alternative

abc_length=${#abc[@]}

for ((i=1; i <= ${#abc[@]}; i++)); do echo "$i:  ${abc[i-1]}"; done

printf '%q\n' "$IFS"

Note that the scope of the newly set IFS variable is limited to the execution of the read command (which leaves the original IFS variable intact).

yabt