Por que o comando cd manipula STDIN diferente de outros comandos?

1

Comandos como cd não podem ter saída canalizada para eles para alterar diretórios - eles exigem argumentos de linha de comando.

Por que o comando cd (e os semelhantes a ele, como mv , cp , & rm ) não funcionam como a maioria dos outros comandos quando se trata de ler em STDIN ? Qual é a lógica por trás de impedir que ele leia a entrada padrão para alterar os diretórios?

O melhor resposta eu poderia encontrar afirmou:

cd is not an external command - it is a shell builtin function. It runs in the context of the current shell, and not, as external commands do, in a fork/exec'd context as a separate process.

No entanto, para mim, a resposta acima não explica nada: Por que cd manipula STDIN diferente de muitos outros comandos que lêem em STDIN ?

    
por Roflicide 04.02.2016 / 23:32

2 respostas

7

Os comandos que leem stdin são quase todos da família de filtros, ou seja, programas que transformam um fluxo de dados de texto em um transformado.

cat , sed , awk , gzip e até sh são bons exemplos desses "filtros".

Os comandos citados, cp , mv e rm definitivamente não são filtros, mas comandos que fazem coisas com os argumentos passados, aqui arquivos ou diretórios.

O comando cd é semelhante a eles, espera um argumento (ou simula um padrão se não for fornecido) e geralmente não produz nada em stdout , embora possa produzir algo nele em alguns casos como quando usando CDPATH .

Mesmo que se deseje criar uma variante cd que retire o diretório de destino de stdin, isso não teria nenhum efeito quando usado em um pipeline no shell Bourne, dash e bash para citar alguns . O último componente do comando que está sendo executado em um subshell, a mudança para um novo diretório não afetará o shell atual. Por exemplo, echo /tmp | cd funcionaria com ksh93 , mas não bash , dash , zsh , sh , ...

cd <(echo /tmp) funcionaria com shells suportando a substituição do processo (pelo menos ksh , bash , zsh ), mas não teria nenhuma vantagem significativa em comparação com cd $(echo tmp)

O único caso de uso que pode ser de interesse seria algo como:

echo tmp | (cd ; pwd)

Por fim, essa variante precisaria resolver o caso em que não foi dado nenhum argumento, mas o comportamento esperado é alterar o diretório para a casa do usuário ou não foi dado nenhum argumento, mas o comportamento esperado é ler o nome do arquivo. diretório de destino do stdin. Como não há maneira confiável de decidir, isso está condenado.

    
por 05.02.2016 / 00:20
3

Os argumentos de linha de comando não são de todo a mesma coisa que stdin; até mesmo comandos que usam os dois geralmente os usam para coisas diferentes. Tome cat por exemplo:

echo foo bar | cat    # outputs "foo bar"
cat foo bar           # looks for files named "foo" and "bar", and concatenates them (if found)

Se você observar a maioria dos outros comandos que lêem stdin, você encontrará coisas semelhantes: eles não tratam argumentos e stdin alternadamente, mas como maneiras de fornecer diferentes tipos de informações para o comando.

Existem alguns comandos que podem ter o mesmo tipo de informação de qualquer forma, mas mesmo nesses casos, geralmente há uma opção que você precisa especificar para especificar qual usar. Por exemplo, perl lê seu programa de stdin, a menos que seja dito para fazer o contrário:

echo 'print 1' | perl    # runs "print 1" as a perl program, which prints "1"
perl -e 'print 1'        # runs "print 1" as a perl program, which prints "1"
perl print 1             # tries to run a file named "print" as a script, giving it the argument "1"

... Então, eu acho que a premissa da pergunta é falsa: a maioria dos comandos não pega o mesmo tipo de informação do stdin que eles usam nos argumentos, então cd não é incomum a esse respeito.

    
por 05.02.2016 / 05:17