La ligne suivante crée file_c-6.txt
mais produit 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 l'on supprime >
il file_c-6.txt
et output 5
:
Je ne peux pas comprendre pourquoi il ne garde pas la valeur de i
dans le premier exemple.
$ 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
Si vous l'exécutez sous strace, vous pouvez voir que la version qui utilise ls
lance la command dans un sous-shell, où la version qui utilise echo l'exécute dans le shell existant.
Comparez la sortie de
$ strace -f /bin/bash -o trace.txt -c 'i=5; echo $i; echo file_c-$((++i)).txt; echo $i' 5 6 6
contre
strace -f /bin/bash -o trace.txt -c 'i=5; echo $i; ls > file_c-$((++i)).txt; echo $i' 5 5
Vous verrez dans le premier:
1251 execve("/bin/bash", ["/bin/bash", "-c", "i=5; echo $i; echo file_c-$(( ++"...], [/* 19 vars */]) = 0 ... 1251 write(1, "5\n", 2) = 2 1251 write(1, "file_c-6.txt\n", 13) = 13 1251 write(1, "6\n", 2) = 2
Et dans la seconde:
1258 execve("/bin/bash", ["/bin/bash", "-c", "i=5; echo $i; ls > file_c-$(( ++"...], [/* 19 vars */]) = 0 ... 1258 write(1, "5\n", 2) = 2 ... 1258 stat("/bin/ls", {st_mode=S_IFREG|0755, st_size=110080, ...}) = 0 1258 access("/bin/ls", R_OK) = 0 1258 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f7301f40a10) = 1259 1259 open("file_c-6.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 1259 dup2(3, 1) = 1 1259 close(3) = 0 1259 execve("/bin/ls", ["ls"], [/* 19 vars */]) = 0 1259 write(1, "71\nbin\nfile_a-5.txt\nfile_b-5.txt"..., 110) = 110 1259 close(1) = 0 1259 munmap(0x7f0e81c56000, 4096) = 0 1259 close(2) = 0 1259 exit_group(0) = ? 1259 +++ exited with 0 +++ 1258 <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 1259 1258 rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f7301570d40}, {0x4438a0, [], SA_RESTORER, 0x7f7301570d40}, 8) = 0 1258 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 1258 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1259, si_status=0, si_utime=0, si_stime=0} --- 1258 wait4(-1, 0x7ffd23d86e98, WNOHANG, NULL) = -1 ECHILD (No child processes) 1258 rt_sigreturn() = 0 1258 write(1, "5\n", 2) = 2
Dans ce dernier exemple, vous voyez le clone
dans un nouveau process (de 1258 -> 1259), alors nous sums maintenant dans un sous-process. L'ouverture de file_c-6.txt qui signifie que nous avons évalué $((++i))
dans le sous-shell, et l'exécution de ls
avec son stdout défini sur ce file.
Enfin, nous voyons que le sous-process se termine, nous récoltons l'enfant, puis nous continuons avec où nous nous sums arrêtés … avec $i
mis à 5, et c'est ce que nous faisons écho à nouveau.
(Souvenez-vous que les changements de variable dans un sous-process ne sont pas répercutés jusqu'au process parent, sauf si vous faites quelque chose explicitement dans le parent pour saisir les changements de l'enfant)