Why is my Bash loop printing each counter value twice?

August 6, 2026 4 answers
Asked by MellowPine42
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?

Answers

CedarMoth19
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.

Reply to this answer
QuartzBison7
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!

Reply to this answer
NorthWren56
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.
Reply to this answer
BrightHarbor31
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.
Reply to this answer

Add your answer

Answers are reviewed before publication.

Related Discussions