Diferença entre subshells e substituição de processos

4

No bash, quero atribuir meu diretório de trabalho atual a uma variável. Usando um subshell, posso fazer isso.

var=$(pwd)

echo $var
/home/user.name

Se eu usar a substituição do processo da seguinte forma:

var=<(pwd)

echo $var
/dev/fd/63

Eu entendi que a substituição do processo é usada principalmente quando um programa não aceita STDIN. Não está claro para mim o que uma substituição de processo faz exatamente e porque ela atribui /dev/fd/63 a var .

    
por PejoPhylo 20.09.2017 / 10:12

1 resposta

3

Uma substituição de comando ( $(...) ) será substituída pela saída do comando, enquanto uma substituição de processo ( <(...) ) será substituída por um nome de arquivo a partir do qual a saída do comando pode ser lida. O comando, em ambos os casos, será executado em um subshell.

No seu caso, a saída de pwd in <(pwd) pode ser encontrada em /dev/fd/63 . Este arquivo deixa de existir assim que o comando que usa a substituição do comando tenha terminado a execução (quando o echo no seu exemplo estiver pronto).

O nome do arquivo retornado por uma substituição de processo é o nome de um descritor de arquivo ou pipe nomeado, não um arquivo regular:

Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files.

Um uso comum de substituição de processo é pré-ordenar arquivos para o comando join :

$ join <( sort file1 ) <( sort file2 )

ou para remover colunas de um arquivo (aqui, a coluna 2 é removida de um arquivo delimitado por tabulação usando cut duas vezes e paste para juntar o resultado):

$ paste <( cut -f 1 file ) <( cut -f 3- file )

A substituição de processos é mais ou menos um atalho sintático para evitar o uso explícito de arquivos temporários.

Ambas as substituições de comandos e substituições de processos são executadas em subshells:

$ echo $( t=1234; echo $t )
1234
$ echo $t
(no output)

Aqui, echo obtém 1234 como um argumento de string da substituição de comandos.

$ cat <( t=4321; echo $t )
4321
$ echo $t
(no output)

Aqui, cat obtém o nome do arquivo de um arquivo (named pipe / file descriptor) como seu argumento. O arquivo contém os dados 4321 .

    
por 20.09.2017 / 10:20