La siguiente línea crea file_c-6.txt
pero genera 5
:
$ i=5; ls file_a-${i}.txt file_b-${i}.txt > file_c-$(( ++i )).txt; echo $i
5
$ cat file_c-6.txt
file_a-5.txt
file_b-5.txt
Si se elimina >
, se enumeraría file_c-6.txt
y generaría 5
:
No puedo entender por qué no mantiene el valor de i
en el primer ejemplo.
$ i=5; ls file_a-${i}.txt file_b-${i}.txt file_c-$(( ++i )).txt; echo $i
file_a-5.txt file_b-5.txt file_c-6.txt
6
echo
lugar dels
, funciona de la segunda manera en ambos casos./bin/echo
conserva la diferencia, por lo que parece que las redirecciones de salida para comandos externos suceden en una subshell.Respuestas:
Si ejecuta esto bajo strace, puede ver que la versión que usa
ls
inicia el comando en un subshell, donde la versión que usa echo lo ejecuta todo en el shell existente.Compare la salida de
en contra
Verás en el primero:
Y en el segundo:
En este último ejemplo, verá
clone
un nuevo proceso (desde 1258 -> 1259), por lo que ahora estamos en un subproceso. La apertura de file_c-6.txt, lo que significa que hemos evaluado$((++i))
en el subshell, y la ejecuciónls
con su stdout establecido en ese archivo.Finalmente, vemos que el subproceso sale, cosechamos al niño, luego continuamos donde lo dejamos ... con el
$i
conjunto a 5, y eso es lo que hacemos eco nuevamente.(Recuerde que los cambios variables en un subproceso no se filtran al proceso padre, a menos que haga algo explícitamente en el padre para tomar los cambios del niño)
fuente
i=5; j=$(( i + 1 )); ls file_a-${i}.txt file_b-${i}.txt > file_c-${j}.txt; i=${j}; echo $i
.