Se for solicitado a um shell que execute um comando provavelmente inútil ( ou parcialmente inútil ) conhecido por terminar, como, por exemplo cat hugeregularfile.txt > /dev/null
, ele pode pular a execução desse comando ( ou executar um equivalente mais barato, por exemplo touch -a hugeregularfile.txt
)?
De maneira mais geral, o shell é semelhante aos compiladores C, pois pode executar qualquer transformação no código-fonte, desde que o comportamento observável externamente seja como se a máquina abstrata o avaliasse?
EDITAR
Nota Bene: Minha pergunta, como originalmente colocada, tinha um título que perguntava se o shell tem permissão para fazer essas otimizações, não se deveria ou mesmo se existem implementações que possam fazê-las. Estou mais interessado na teoria do que na prática, embora ambas sejam bem-vindas.
cat
ting faz uma grande diferença. O shell pode saber que o arquivo é um dispositivo, mas não precisa ser confiável.wc
, por exemplo). Mas, até onde sei, o POSIX não se posiciona sobre a otimização de shell; Ou faz?ksh
. Como se não dissessem processo separado, mas ambiente de subcamação para permitir otimizações de economia de forquilha.Respostas:
Não, isso seria uma má ideia.
cat hugeregularfile.txt > /dev/null
etouch -a hugeregularfile.txt
não são os mesmos.cat
lerá o arquivo inteiro, mesmo se você redirecionar a saída para/dev/null
. E ler o arquivo inteiro pode ser exatamente o que você deseja. Por exemplo, para armazená-lo em cache, para que as leituras posteriores sejam significativamente mais rápidas. A concha não pode conhecer sua intenção.Da mesma forma, um compilador C nunca otimizará a leitura de um arquivo, mesmo que você não veja o que lê.
fonte
true
efalse
) tem efeitos colaterais em potencial, e os efeitos colaterais são quase sempre o ponto de chamar o comando. O shell não podia conhecer esses efeitos colaterais com antecedência (para programas externoscat
) sem resolver o problema da parada. Portanto, com razão, não tente e assume que você quis dizer o que disse.cat
. De fato, vocêcat
pode fazer qualquer coisa, desde a formatação do disco rígido até o download da Internet.true
efalse
definido$?
.cat
e/dev/null
têm significados típicos, mas não garantem que se comportem dessa maneira. Para realizar otimizações e garantir nenhuma alteração no comportamento esperado, a otimização só pode ser permitida envolvendo construções implementadas no próprio shell e não coisas encontradas no ambiente de execução ... não importa o quão intuitivo possa ser o nome deles.Não, já que
/dev/null
é apenas um nome, que pode ser usado para qualquer outro dispositivo ou arquivo que não seja o que "normalmente" é um coletor de dados.Portanto, um shell (ou qualquer outro programa) não tem idéia, com base no nome, se o arquivo para o qual está gravando está fazendo algo "de verdade" com os dados. Também existem AFAIK que nenhum sistema chama pelo programa shell, para determinar que, por exemplo, o descritor de arquivo não está realmente fazendo nada.
Sua comparação com a otimização de código ausente em um programa C não funciona, pois um shell não possui a visão geral total que um compilador C possui sobre um pedaço de código-fonte. Um shell não sabe o suficiente sobre
/dev/null
como otimizar seu exemplo, mais como um compilador C não sabe o suficiente sobre o código em uma chamada de função à qual ele se vincula dinamicamente, para não fazer a chamada.fonte
/dev/null
especialmente, às vezes. Um built-in que tem seu stdout direcionado para/dev/null
, por exemploecho foo >/dev/null
, não resultará em gravações/dev/null
. Não faz nada de especial se estiver invocando um comando não interno (comocat file >/dev/null
).cat
também poderia ser outra coisa. Qualquer outra coisa de fato./dev/null
é uma das poucas caminhos normalizados , juntamente com/dev/tty
,/dev/console
,/tmp
,/dev/
e/
.cat
é um ksh93 embutido (não ativado, a menos que você o coloque/opt/ast/bin
antes/bin
(ou onde houvercat
)$PATH
). E sim, emboracat file > /dev/null
com esse built-in façaread
o conteúdo defile
, ele não o grava em / dev / null (embora o abra e faça o fstats).Ele não otimiza os comandos em execução (e você já recebeu várias respostas excelentes, informando por que não deveria), mas pode otimizar os garfos, pares de tubos / soquetes e leituras em alguns casos. O tipo de otimizações que ele pode fazer:
trap
s tenham sido definidos. Por exemplo, emsh -c ls
, a maioria dassh
implementações (bash
,mksh
,ksh
,zsh
,yash
, algumas versões doash
) não vai desembolsar um processo a ser executadols
.ksh93
, a substituição de comando não criará um processo de tubulação ou bifurcação até que um comando externo seja chamado ($(echo foo)
por exemplo, será expandido parafoo
sem um tubo / par de soquete ou forquilha).read
built-in de alguns shells (bash
, AT&Tksh
) não fará leituras de byte único se eles detectarem que stdin é procurável (nesse caso, eles farão leituras grandes e buscarão o final do que devem ler).fonte
ksh93
é o shell que lidera o caminho da frente de otimização, pois seu objetivo é / deveria ser visto como compatível com linguagens de programação comoperl
. Assim, você pode consultar aksh
documentação, o código (boa sorte) e a lista de discussão para obter mais informações.sh -c 'ps -p "$$"'
o que lhe daráps
e nãosh
com essassh
implementações, ou com strace / pequena / Tusc ...ksh -c 'ps; ps'
e bash -c 'ps; ps' é interessante. O Ksh93 vai mais longe na sua otimização.ksh
estamos falando aqui.mksh
se comporta comobash
. Esse comportamento é principalmente destinado a otimizar coisas comosystem("some command")
. Observe que há um efeito colateral dessa otimização quando se trata do status de saída dos processos terminados por um sinal (em alguns shells).ksh93
costumava ter um bug , pois fazia a otimização mesmo quando as armadilhas eram definidas.Ao ver
cat hugeregularfile.txt > /dev/null
, a concha não pode acreditar que a ação é inútil -cat
não faz parte da concha e poderia fazer qualquer coisa na teoria e também na prática.Por exemplo, o usuário pode ter renomeado o executável
rm
paracat
e, de repente, a linha executa um comportamento observável externamente, ou seja, removendo o arquivo.O usuário pode ter compilado uma versão
cat
que entra em um loop infinito; portanto, o shell não pode assumir que ele é conhecido por terminar, como você sugere.Alguém pode ter instalado uma versão
cat
que funcione conforme o planejado, mas com um efeito colateral extra de instalar um rootkit, se ele for executado com privilégios adequados - novamente, o shell deve executá-lo devidamente.fonte
mksh
ele realmente otimizaV=$(cat file)
, tornando-o um builtin. Portanto, o shell pode otimizá-lo, mas não transformá- lo em apenas atouch -a
.cat
é um embutido nomksh
, mas que resorts embutidas para o sistema estácat
se aprovada qualquer opção, e é por isso com GNUcat
,mksh -c 'cat /dev/null --help'
não produz o mesmo resultado quebash -c 'cat /dev/null --help'
, masmksh -c 'cat --help /dev/null'
lhe dá o mesmo quebash -c 'cat --help /dev/null'
(comomksh
gato builtin Analisa as opções POSIX enquanto o GNU cat os analisa da maneira GNU).V=$(cat file)
pode ser otimizado comV=$(< file)
. Isso acelera as coisas, mesmo sem um builtincat
.