Considere as duas amostras de casca
$ ls
myDoc.html
SomeDirectory
someDoc.txt
e
$ echo $(ls)
myDoc.html SomeDirectory someDoc.txt
A primeira é executada ls
e, como eu entendo, anexa o conteúdo do diretório de trabalho atual ao stdout
arquivo (que é o que o terminal exibe). Isso está correto?
O segundo pega o valor do ls
comando (que significa o conteúdo do diretório de trabalho atual) e o imprime no stdout
arquivo. Isso está correto?
Por que os dois comandos fornecem saídas diferentes?
ls
por si só, não fornece vários itens por linha?echo *
?Respostas:
Quando você executa este comando:
o terminal exibe a saída de
ls
.Quando você executa este comando:
o shell captura a saída
$(ls)
e executa a divisão de palavras nele. Com o padrãoIFS
, isso significa que todas as seqüências de espaço em branco, incluindo caracteres de nova linha, são substituídas por um único espaço em branco. É por isso que a saída deecho $(ls)
aparece em uma linha.Para uma discussão avançada sobre divisão de palavras, consulte as Perguntas frequentes de Greg .
Suprimindo a divisão de palavras
O shell não executa a divisão de palavras em cadeias entre aspas. Assim, você pode suprimir a divisão de palavras e reter a saída multilinha com:
ls
e saída multilinhaVocê deve ter notado que,
ls
às vezes, imprime mais de um arquivo por linha:Esse é o padrão quando a saída de
ls
vai para um terminal. Quando a saída não vai diretamente para um terminal,ls
altera seu padrão para um arquivo por linha:Esse comportamento está documentado
man ls
.Outra sutileza: substituição de comando e novas linhas à direita
$(...)
é substituição de comando e o shell remove os caracteres de nova linha à direita da saída da substituição de comando . Isso normalmente não é perceptível porque, por padrão,echo
adiciona uma nova linha ao final de sua saída. Portanto, se você perder uma nova linha no final$(...)
e a ganharecho
, não haverá alterações. Se, no entanto, a saída do seu comando terminar com 2 ou mais caracteres de nova linha enquantoecho
adicionar apenas um, sua saída estará faltando uma ou mais novas linhas. Como exemplo, podemos usarprintf
para gerar caracteres de nova linha à direita. Observe que os dois comandos a seguir, apesar do número diferente de novas linhas, produzem a mesma saída de uma linha em branco:Esse comportamento está documentado
man bash
.Outra surpresa: expansão do nome do caminho, duas vezes
Vamos criar três arquivos:
Observe a diferença entre
ls file?
eecho $(ls file?)
:No caso de
echo $(ls file?)
, o arquivo globfile?
é expandido duas vezes , fazendo com que os nomes dos arquivosfile1
efile2
apareçam duas vezes na saída. Isso ocorre porque, como Jeffiekins aponta, a expansão do nome do caminho é realizada primeiro pelo shell antes dels
ser executada e depois novamente antes daecho
execução.A segunda expansão do nome do caminho pode ser suprimida se usamos aspas duplas:
fonte
isatty
você pode verificar se stdout é um tty, ls usa isso para determinar se deve usar cores ou não.$( )
realmente fornece uma barreira de sintaxe para que você não precise interpolar?$()
fornece uma barreira de sintaxe.echo
comando expandirá o curinga . Por exemplo, sels
retornar arquivo? arquivo1 arquivo2 , entãoecho $(ls)
retornará o arquivo? arquivo1 arquivo2 arquivo1 arquivo2 .echo
não expande curingas; o shell faz antes de passar a expansão resultante como argumentos paraecho
.ls
sabe se está enviando saída para um terminal ou não.A execução
ls
em um prompt de comando gravará em seu pseudo-tty. Redirecionar a saída dels
geralmente não vai para um pseudo-tty els
formatará a saída de maneira diferente.fonte