Por que 'sort (ls -l)' funciona, mas 'sort (ls -l)' falha?

33

Hoje estou aprendendo algo sobre o fifo com este artigo: Introdução aos pipes nomeados , que menciona cat <(ls -l) .

Eu fiz alguns experimentos usando sort < (ls -l) , que mostra um erro:

-bash: syntax error near unexpected token '(''

Então eu descobri que eu coloquei um espaço extra no comando.

Mas por que esse comando extra levará a essa falha? Por que o símbolo de redirecionamento deve estar próximo do ( ?

    
por Zen 11.09.2015 / 13:03

2 respostas

46

Porque esse não é um < , é um <() que é completamente diferente. Isso é chamado de substituição de processos , é uma característica de certos shells que permitem para usar a saída de um processo como entrada para outro.

Os operadores > e < redirecionam a saída e a entrada de arquivos . O operador <() lida com comandos (processos), não com arquivos. Quando você corre

sort < (ls)

Você está tentando executar o comando ls em um subshell (é o que os parênteses significam) e, em seguida, passar esse subshell como um arquivo de entrada para sort . Isto, no entanto, não é aceito sintaxe e você recebe o erro que você viu.

    
por 11.09.2015 / 13:12
22

Porque é assim que deve ser.

<(...) in bash é a sintaxe para substituição de processos. É copiado do mesmo operador em ksh .

< , ( , ) , | , & , ; são tokens especiais lexicais em bash que são usados para formar operadores especiais em diferentes combinações. < , <( , << , <& ... cada um tem seu papel. < é para redirecionamento. <file , < file redirecionaria a entrada de um arquivo. <'(file)' redirecionaria a entrada de um arquivo chamado (file) , mas <(file) é um operador diferente que não é um operador de redirecionamento.

< (file) seria < seguido por (file) . Nesse contexto, em bash , (file) não é válido. (...) pode ser válido como um único token em alguns contextos como:

(sub shell)
func () {
  ...
}
var=(foo bar)

Mas não em

sort < (cmd)

No shell fish , é diferente. Em fish , (...) é para substituição de comando (o equivalente a $(...) in bash ). E < é para redirecionamento de entrada, como em shells semelhantes a Bourne.

Então, em fish :

sort <(echo file)

seria o mesmo que:

sort < (echo file)

Isto é:

sort < file

Mas isso é algo completamente diferente da substituição do processo de bash .

No shell yash , outro shell POSIX, <(...) não é para substituição de processo , mas para redirecionamento de processo

Lá,

sort <(ls -l)

Abreviação de:

sort 0<(ls -l)

é um operador de redirecionamento. É mais ou menos equivalente a:

ls -l | sort

Enquanto em bash , o <(ls -l) é expandido para o caminho de um canal, então é mais parecido com:

ls -l | sort /dev/fd/0

Em zsh , (...) está sobrecarregado como um operador de globbing ( (*.txt|*.png) seria expandido para txt e png files) e como qualifier glob ( *(/) por exemplo expande para arquivos de diretório). / p>

Em zsh , em:

sort < (ls -l)

Esse (ls -l) seria tratado como um qualificador glob. O qualificador l glob deve corresponder ao número de links e esperar um número após l (como em ls -ld ./*(l2) listaria os arquivos com 2 links), por isso você obtém um erro zsh: number expected .

sort < (w) teria dado um erro zsh: no matches found: (w) , pois (w) corresponde aos arquivos com nome vazio que são graváveis.

sort < (w|cat) teria classificado o conteúdo dos arquivos w e / ou cat no diretório atual ...

    
por 11.09.2015 / 14:28