La lógica aquí es que su uso de &&
ya es comprobación de errores. De la misma manera que bash no trata una falla dentro de un if
condición que vale la pena abortar, incluso con set -e
.
Cuando envuelve los comandos entre paréntesis, en realidad está ejecutando esos comandos dentro de una subcapa, por lo que el script en sí solo ve el retorno de esa subcapa, es decir, no sabe que &&
está involucrado en absoluto, por lo que aborta como esperabas.
Cita el manual de referencia:
El shell no sale si el comando que falla es parte de la lista de comandos inmediatamente después de una palabra clave while o till, parte de la prueba en una declaración if, parte de cualquier comando ejecutado en un &&o || list excepto el comando que sigue al &&final o ||, cualquier comando en una canalización excepto el último, o si el estado de retorno del comando se invierte con !