Why is my Bash loop printing each counter value twice?

0
0
Asked By MellowPine42 On

I have a shell script that gets the number of CPUs, loops from 0 up to that number, prints the counter, creates a temporary file for each CPU, and increments the counter. The script is:

#!/usr/local/bin/bash
StartUp_Run=false
Iterator_For_File_Toucher_With_NCPU_While=0
Total_NCPU_For_File_Toucher_With_NCPU_while=$(nproc --all)

while true
do
if [ "$StartUp_Run" = false ]; then
while [ "$Iterator_For_File_Toucher_With_NCPU_While" -lt "$Total_NCPU_For_File_Toucher_With_NCPU_while" ]; do
echo "$Iterator_For_File_Toucher_With_NCPU_While"
touch "core${Iterator_For_File_Toucher_With_NCPU_While}-temp_orders.csv"
let "Iterator_For_File_Toucher_With_NCPU_While+=1"
done
echo "ncpu amount = $Total_NCPU_For_File_Toucher_With_NCPU_while"
StartUp_Run=true
fi
done

When I run it using `sh LastStage.sh`, I see values such as 0, 1, 1, 2, 2, and so on. Why is every value except the first being printed twice?

4 Answers

Answered By BrightHarbor31 On

If the output still looks wrong, enable tracing immediately after the shebang with `set -x` and run the script with Bash. The trace will show every command actually executed and can reveal an unsaved extra `echo`, an alias or function named `let`, or the fact that a different shell is interpreting the file.

Answered By NorthWren56 On

There are a few portability and correctness issues worth fixing too. Use `=` rather than `==` in the single-bracket test, quote variables, and avoid the endless `while true` loop unless it has a real purpose or a delay. Also, `touch` updates the timestamp of an existing file; if you only want to ensure that a file exists, redirecting output to it may be more appropriate depending on your goal.

Answered By QuartzBison7 On

The main issue is that you're explicitly running the file with `sh`, so the Bash shebang is ignored. `sh` may point to a different shell, such as `dash`, and its handling of `let` can differ. Make the script executable and run it directly instead:

`chmod +x LastStage.sh`
`./LastStage.sh`

Alternatively, invoke Bash explicitly with `bash LastStage.sh`. Also check that the file you're running is saved and doesn't contain an extra `echo` after the increment. In Bash, the loop as shown prints each counter only once.

MellowPine42 -

That was the issue—thanks!

Answered By CedarMoth19 On

The loop can be simplified considerably. There is no need for an infinite outer loop because the inner loop already performs the one-time initialization. Use Bash arithmetic instead of `let`, and quote expansions:

`cpu=0`
`ncpu=$(nproc --all)`
`while (( cpu < ncpu )); do`
` echo "$cpu"`
` touch "core${cpu}-temp_orders.csv"`
` ((cpu++))`
`done`
`echo "ncpu amount = $ncpu"`

This should produce one line for each value from 0 through `ncpu - 1`.

MapleOrbit8 -

`let i++` and `((i++))` are equivalent in Bash, but arithmetic syntax makes it clearer that the command is intended for numeric operations. The important part here is using Bash consistently rather than running the script through an arbitrary `sh` implementation.

Related Questions

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.