Por que ls
requer um processo separado para sua execução? Eu sei a razão pela qual comandos como cd
não podem ser executados pelo mecanismo de bifurcação, mas há algum dano se ls
for executado sem bifurcação?
Por que ls
requer um processo separado para sua execução? Eu sei a razão pela qual comandos como cd
não podem ser executados pelo mecanismo de bifurcação, mas há algum dano se ls
for executado sem bifurcação?
Respostas:
A resposta é mais ou menos que ls
é um executável externo. Você pode ver sua localização executando type -p ls
.
Por que não está ls
embutido no shell, então? Bem, por que deveria ser? O trabalho de um shell não é abranger todos os comandos disponíveis, mas fornecer um ambiente capaz de executá-los. Alguns shells modernos têm echo
, printf
e seus tipos como internos, que tecnicamente não precisam ser integrados, mas são feitos por motivos de desempenho quando são executados repetidamente (principalmente em loops apertados). Sem torná-los integrados, o shell precisaria forçar e executar um novo processo para cada chamada, o que poderia ser extremamente lento.
No mínimo, a execução ls
, um executável externo, exige a execução de uma das famílias de exec de chamadas do sistema. Você poderia fazer isso sem bifurcar, mas substituiria o shell principal que você está usando. Você pode ver o que acontece nessa instância, fazendo o seguinte:
exec ls; echo "this never gets printed"
Como a imagem de processo do seu shell é substituída, o shell atual não fica mais acessível depois de fazer isso. Para que o shell possa continuar executando após executar ls, o comando teria que ser incorporado ao shell.
A bifurcação permite a substituição de um processo que não é seu shell principal, o que significa que você pode continuar executando seu shell posteriormente.
echo
, printf
, etc.
cd
não é um executável externo?
cd
executável em sistemas operacionais compatíveis com POSIX ( ver aqui ). Se você realmente deseja chdir () no processo atual, é necessário integrá-lo no shell.
O Manual de Referência do Bash declara:
Os comandos internos são necessários para implementar funcionalidades impossíveis ou inconvenientes de serem obtidas com utilitários separados.
Ou seja, os shells são projetados para incluir apenas comandos internos se:
O ls
comando não se encaixa em nenhum dos requisitos acima.
No entanto , não há restrição de programação que impeça ls
a implementação como um interno, que esteja sendo executado no mesmo processo que o interpretador do bash. Os motivos de design para os comandos não serem implementados como embutidos no shell são:
Em relação ao primeiro motivo - você deseja que o shell seja o mais independente e resistente possível. Você não deseja que o shell fique preso em ls
uma montagem NFS que "não está respondendo ainda está tentando".
Com relação ao segundo motivo - Em muitos casos, convém usar um shell para um sistema que usa o Busybox ou outro sistema de arquivos com uma ls
implementação diferente . Ou use a mesma fonte de shell em sistemas operacionais que possuem ls
implementações diferentes .
Em relação à terceira razão - Para expressões como find . -type d | xargs ls -lad
seria difícil ou impossível implementar ls
o mesmo processo que o interpretador de shell.
Em relação à quarta razão - alguns ls
comandos podem demorar muito para serem concluídos. Você pode querer que o shell continue fazendo outra coisa enquanto isso.
Nota: Veja este post útil de Warren Young em resposta a uma pergunta semelhante.
ls
para um processo externo. Isso poderia ser feito, mas seria complicado.
bash
saída alias | grep ls
. inputcat /etc/passwd | while read a; do echo "$a"; done
ls
não requer um processo separado. Pouquíssimos comandos realmente requerem um processo separado: somente aqueles que precisam alterar privilégios.
Como regra, os shells implementam comandos como internos apenas quando esses comandos precisam ser implementados como internos. Comandos como alias
, cd
, exit
, export
, jobs
, ... necessidade de ler ou modificar algum estado interno do shell, e, portanto, pode não ser programas separados. Comandos que não possuem esses requisitos podem ser comandos separados; Dessa forma, eles podem ser chamados de qualquer shell ou outro programa.
Observando a lista de componentes internos no bash, apenas os seguintes componentes internos podem ser implementados como comandos separados. Para alguns deles, haveria uma leve perda de funcionalidade.
command
- mas perderia sua utilidade em situações em PATH
que não pode ser configurado corretamente e o script está sendo usado command
como parte da configuração.echo
- é um builtin para eficiência.help
- ele poderia usar um banco de dados separado, mas a incorporação do texto de ajuda no executável do shell tem a vantagem de tornar o executável independente.kill
- há duas vantagens em ter um built-in: ele pode reconhecer designações de trabalho além de IDs de processo e pode ser usado mesmo quando não há recursos suficientes para iniciar um processo separado.printf
- pelo mesmo motivo echo
e também para oferecer suporte à -v
opção de colocar a saída em uma variável.pwd
- o built-in oferece a capacidade adicional de rastreamento de diretório lógico atual (deixando os links simbólicos intactos em vez de expandi-los).test
- é um recurso embutido para eficiência (e o bash também faz mágica com arquivos chamados /dev/fd/…
em alguns sistemas operacionais).Algumas conchas oferecem um número significativo de componentes adicionais. Há sash , que é um shell projetado para ser um binário independente para reparos de emergência (quando alguns comandos externos podem não ser utilizáveis). Possui um built-in ls
chamado -ls
, assim como outras ferramentas como -grep
e -tar
. Os recursos internos do Sash têm menos recursos do que os comandos completos. O Zsh oferece alguns recursos similares em seu módulo zsh / files . Não possui ls
, mas expansão de curinga ( echo *
) e zstat
pode ter uma função semelhante.
Eu acho que algo que as pessoas estão perdendo aqui é a complexidade de cisalhamento do ls
programa GNU no Linux. Comparando o tamanho do executável de ls
ao bash
e dash
conchas no meu sistema Debian, vemos que é muito grande:
graeme@graeme:~$ ls -lh /bin/{ls,bash,dash}
-rwxr-xr-x 1 root root 953K Mar 30 2013 /bin/bash
-rwxr-xr-x 1 root root 115K Dec 25 20:25 /bin/dash
-rwxr-xr-x 1 root root 108K Jul 20 22:52 /bin/ls
Incluir uma ls
versão com todos os recursos da versão GNU bash
aumentaria o tamanho do executável em 10%. É quase do mesmo tamanho que a dash
concha completa !
A maioria dos componentes internos do shell são escolhidos porque se integram ao shell de uma maneira que os executáveis externos não podem (a questão aponta cd
, mas outro exemplo é a versão bash da kill
integração com o controle do trabalho do bash) ou porque são comandos muito simples de implementar, oferecendo uma grande recompensa por velocidade versus tamanho ( true
e false
é o mais simples possível).
O GNU ls
teve um longo ciclo de desenvolvimento e implementa várias opções para personalizar quais / como os resultados são exibidos. O uso de um built-in ls por padrão perderia essa funcionalidade ou aumentaria significativamente a complexidade e o tamanho do shell.
Faça o que você está procurando:
printf "%s\n" *
Além disso, você pode armazenar nomes de arquivos na matriz:
files=(`printf "%s\n" *`) #items are separated by whitespace
echo ${#files[*]} files
for index in ${!a[*]}
do printf "%d: %s\n" $index ${a[$index]};
done
Mas ele não se importa com espaços em nomes.
Isso passa para variável e se preocupa com espaços:
printf "%s\n" * | while read a; do echo $a; done
ls
seja um programa externo,echo *
ouecho * .*
(dependendo das opções do shell) faz um bom trabalho ao listar arquivos sem bifurcar-se.