Solution 1:

With the second command

:~$ ls macreave.sh fgvdvg > testo 2>&1

you will cause the stderr ouput of ls to be written to the same filedescriptor than stdout (2>&1) and the stdout to the file testo: so you have a unique flux that finish in your file.

With the first command instead

ls macreave.sh fgvdvg > testo 2> testo

you are redirecting independently to the same file testo. The problem is pipings and redirections can be asyncronus (see this answer too); you have 2 fluxes that finish in your file both recreating it.

It seems that:

  • the faster was the stderror (for few bytes) that creates a file testo (>) and write inside ls: cannot a
  • then it is arrived the stdout that recreates the same file (>) erasing what inside and puts the output macreave.sh
  • finally it is arrived the second part of stderr that writes in the file what remains ccess fgvdvg: No such file or directory.

Maybe if you execute again you will have a different result.

References

  • Bash manual
  • Pipes, how do data flow in a pipeline