Esattamente; la fork crea un nuovo processo che è un clone esatto di quello corrente, e nel processo nuovo restituisce 0, mentre nel processo vecchio restituisce il PID del processo nuovo. Il processo nuovo in questo caso chiude il descrittore file di stdout (close(1)) e collega stdout ad un'estremità della pipe (dup(pipefd[1]); questa riga funziona perché dup duplica il descrittore file passatogli, assegnando al nuovo descrittore l'ID più basso disponibile, che in questo caso è 1, che è quello che corrisponde a stdout). Quindi chiude il descrittore corrispondente all'altra estremità della pipe e chiama la exec, che rimpiazza completamente il "contenuto" del processo corrente con ls; il processo però mantiene diversi attributi precedenti all'exec, tra cui i descrittori file, per cui ls, scrivendo su stdout, andrà in realtà a scrivere sull'estremità della pipe che è stata duplicata prima.
Il processo vecchio, invece, collega l'altra estremità della pipe a stdin (chiudendo il descrittore 2 e duplicando l'altra estremità della pipe in maniera analoga a quanto fatto dal processo figlio).