2

Within a bash script, I'm trying to pull all files with an extension '.jstd' into an array, loop over that array and carry out some action.

My script is failing to copy the path of each script into the array.

I have the following script.

#!/bin/bash

IFS=$'\n'
file_list=($(find '/var/www' -type f -name "*.jstd"))
for i in "${file_list[@]}"; do
    echo "$i"
done

echo $file_list
unset IFS

The line file_list=($(find '/var/www' -type f -name "*.jstd")) works fine in the terminal, but fails in the script with:

Syntax error: "(" unexpected

I've googled, but failed. All ideas gratefully received.

edit: In case it helps in reproduction or clues, I'm running Ubuntu 12.04, with GNU bash, version 4.2.25(1)-release (i686-pc-linux-gnu)

4
  • 2
    Don't do this. See mywiki.wooledge.org/DontReadLinesWithFor for reasons why. Do this correctly mywiki.wooledge.org/BashFAQ/001 . Also mapfile might be useful here for bash 4+. Commented Oct 13, 2014 at 19:47
  • 3
    That error indicates that you aren't invoking your script with bash. Are you perhaps running sh yourscript? If so, the manual use of sh will override the #!/bin/bash shebang. (Also, allow me to strongly echo the advice given by @EtanReisner; reading from find into an array in this manner is a very lossy process). Commented Oct 13, 2014 at 20:02
  • 1
    ...also, echo $file_list doesn't make sense for an array. printf '%q\n' "${file_list[@]}" would make sense, sure, but as it is your code only prints the first array entry, and that after string-splitting and glob-expanding it (since you don't quote correctly). Commented Oct 13, 2014 at 20:04
  • Yes, I was running through sh! Excellent spot and newbie error. Cheers. If you want to make that an answer, I can accept. Reap the rewards of your knowledge. Commented Oct 13, 2014 at 20:06

1 Answer 1

5

This is precisely the error you would get if your shell were /bin/sh on Ubuntu, not bash:

$ dash -c 'foo=( bar )'
dash: 1: Syntax error: "(" unexpected

If you're running your script with sh yourscript -- don't. You must invoke bash scripts with bash.


That being given, though -- the better way to read a file list from find would be:

file_list=( )
while IFS= read -r -d '' filename; do
  file_list+=( "$filename" )
done < <(find '/var/www' -type f -name "*.jstd" -print0)

...the above approach working correctly with filenames containing spaces, newlines, glob characters, and other corner cases.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the tip with +=, I always find out something new about bash :)
BTW, my read command was actually slightly wrong -- wasn't clearing IFS, so whitespace on the end of filenames would be silently deleted. That's fixed now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.