5 ms·
For me, the biggest gotcha in bash is whether or not a sub-process/shell will be invoked, which can affect things like mutable variables and the number of open
by chriswarbo 9y ago
For me, the biggest gotcha in bash is whether or not a sub-process/shell will be invoked, which can affect things like mutable variables and the number of open file handles. For example:
COUNT=0
someCommand | while read -r LINE
do
COUNT=$(( COUNT + 1 ))
done
echo "$COUNT"
This will always print `0`, since the `COUNT=` line will be run in a sub-process due to the pipe, and hence it can't mutate the outer-process's `COUNT` variable. The following will count as expected, since the `<()` causes `someCommand` to run in a sub-process instead:
COUNT=0
while read -r LINE
do
COUNT=$(( COUNT + 1 ))
done < <(someCommand)
echo "$COUNT"
Another issue I ran into is `$()` exit codes being ignored when spliced into strings. For example, if `someCommand` errors-out then so will this:
set -e
FOO=$(someCommand)
BAR="pre $FOO post"
Yet this will fail silently:
set -e
BAR="pre $(someCommand) post"
- Hello71 9y ago$ bash -ec 'BAR="pre $(someCommand) post"; echo hi' bash: someCommand: command not found $ I get the same behavior in bash, zsh, dash, and busybox sh. shbot says the same for bash versions since 1.14, ksh, and even the original bourne shell (modified to use ` instead of $()).
- maksimum 9y agoI think I've run into the first issue you describe, and I'm having a hell of a time trying to understand it. Would you mind taking a look at my example and helping me out? Consider the following: cd /tmp/ echo -e "hello world\nhello world\n:)" >> hello.txt cat hello.txt Outputs: hello world hello world :) Then running bash -c 'sed s/"hello"/"hiiii"/ hello.txt | tee hello.txt' cat hello.txt yields hiiii world hiiii world :) Reseting to the original `hello.txt` and running ssh localhost -t 'cd /tmp && sed s/"hello"/"hiiii"/ hello.txt | tee hello.txt' cat hello.txt yields an empty file. Replacing the command with ssh localhost -t 'cd /tmp && sed s/"hello"/"hiiii"/ hello.txt >> hello.txt' yields hello world hello world :) hiiii world hiiii world :) I'm trying to figure this out so I can publish a script to set up a test env for a package I'm trying to publish, and somewhat stuck on this step...
- mkl 9y agoYou're using hello.txt as both an input file and an output file, which seems like it's just asking for race-condition problems. What about using sed -i to make changes to the file, and not doing any bash redirection? Alternatively, if the real problem is more complex than that, try using a different name for the output file and rename after it's finished.
- half-kh-hacker 9y agoThe `>>` operator in use is /appending/ to the file. Also, as mentioned in a sibling comment, your hello.txt is both an input and output.
- MPSimmons 9y agolet COUNT=COUNT+1 is all you need
- tux1968 9y agoor: let count++