As stated by the other answers:
- The problem is the `;` after the `&`.
- Deleting the `;` after the `&` will result in a command
that will run without shell syntax errors.
However, it is unlikely to function correctly,
because it creates a race condition.
The OP stated that he resolved the race condition by adding a 3 second delay.
Nobody mentioned:
- A 3 second delay might work today.
Tomorrow, the computer might be more sluggish, and it could fail again.
Next year, the script might be modified to be more time-consuming,
and it could fail again.
The probability of failure goes down if you increase the delay
by an order of magnitude, by which I mean 30 seconds.
Of course this means that the script processes will (probably / presumably)
be running essentially sequentially, and not concurrently (in parallel),
thus defeating the purpose of making the processes asynchronous.
- If running multiple instances of the script is a requirement,
it’s probably best to modify the script to accept the number parameter
on the command line:
```
for ((i=114;i<=255;i++)); do python DoMyScript.py --number="$i" & done
```
and do away with the file.
- If changing the script is not an option, this solution should work:
```
for i in {114..125}; do ( subdir="dir.$i" && mkdir "$subdir" && cd "subdir" &&
echo "$i" > numbers.txt && python ../DoMyScript.py; cd .. && rm -r "$subdir" ) & done
```
This gives each script process a separate `numbers.txt` file,
by giving it a separate directory to run in.
The directory is created and deleted, and the script is run, in a subshell.
- If `DoMyScript.py` accesses any files other than `numbers.txt`
by relative pathnames,
the above command will need to be adjusted to accommodate that.
- The above was inspired by [glenn jackman’s answer][1]
(although I believe that mine will work and his won’t).
- If command *`B`* depends on the success of command *`A`*,
then <code><i>A</i> && <i>B</i></code> is better defensive programming
than <code><i>A</i>; <i>B</i></code>.
But it’s probably not the ideal way to handle this situation.
If `mkdir dir.114` fails, then the next 111 attempts are likely to fail also,
and you’ll get 112 error messages.
It would be better to abort the loop if a fatal error occurs.
The fact that the action is happening in an asynchronous subshell
makes this somewhat tricky.
```
for i in {114..125}; do
{ subdir="dir.$i" && mkdir "$subdir" && echo "$i" > "$subdir"/numbers.txt; } || break;
( cd "$subdir" && python ../DoMyScript.py; cd .. && rm -r "$subdir" ) & done
```
will cause the loop to abort if a `mkdir`
or an <code>echo <i>value</i> > <i>file</i></code> command fails.
- It might be better to work in a directory
that is ‘‘guaranteed’’ to be writable, like `/tmp`.
However, this increases the risk that your command
will collide (interfere) with some other process.
- You can mitigate this by adding `$$` to the directory name;
e.g., `dir.$$.$i` or even `dir.$BASHPID`.
- This would not eliminate the risk that the `mkdir`
or the file creation might fail because the filesystem is full.
- Note that the above code will keep on going
and remove the temporary directory even if the script fails.
You might want to do something else in that situation.
- Oops.
If, for some reason,
the `mkdir "$subdir"` succeeds but the `cd "$subdir"` fails,
this will go ahead and do `cd .. && rm -r "$subdir"`.
If there is a directory with a name like `dir.114` in your parent directory
(i.e., parallel to your current directory), it will be removed.
I believe that you can (at least somewhat) fix this
by changing the last line to
```
( cd "$subdir" && { python ../DoMyScript.py; cd ..; } && rm -r "$subdir" ) & done
```
or by using absolute paths; e.g., `subdir="$PWD/dir.$i"`.
[1]: https://unix.stackexchange.com/q/91684/80216#91713