O /usr/bin/printf
comprimento da lista de argumentos util é limitado ao comprimento máximo da linha de comando do shell ( ou seja getconf ARG_MAX
, no meu sistema seria 2097152 ); exemplo:
# try using a list that's way too long
/usr/bin/printf '%s\n' $(seq $(( $(getconf ARG_MAX) * 2 ))) | tail -1
Resultado:
bash: /usr/bin/printf: Argument list too long
Hoje sou informado que os embutidos do shell printf
não têm esse limite; teste:
printf '%s\n' $(seq $(( $(getconf ARG_MAX) * 2 ))) | tail -1
Resultado:
4194304
Perguntas:
Uma olhada rápida
man bash dash
não parece dizer muito sobre essa vantagem do builtprintf
-in . Onde está documentado?O builtin
printf
s ( por exemplobash
) tem um comprimento máximo de lista de argumentos em caracteres e, se sim, qual é esse comprimento?
Não é realmente o trabalho do manual defender o uso de qualquer utilidade em particular. Ele deve descrever principalmente os utilitários integrados disponíveis.
As vantagens de usar um utilitário interno sobre um externo são principalmente a velocidade e a disponibilidade de recursos estendidos ( pode,
printf
porbash
exemplo, escrever diretamente em uma variável com-v varname
, o que nenhum externoprintf
poderia fazer).A execução de utilitários externos é lenta em comparação com a execução de um utilitário interno, especialmente se for feito frequentemente em um loop, e, como você notou, eles também permitem listas de argumentos mais longas (isso não é algo que apenas o interno
printf
permite , mas todos os utilitários integrados).O comprimento da lista de argumentos para o
printf
utilitário integradobash
é limitado pelas restrições de recursos nobash
próprio processo. Em alguns sistemas, isso pode até significar que você pode usar a maior parte da RAM disponível para construir sua lista de argumentos de linha de comando.A documentação de onde você encontraria essas várias informações é
bash
código-fonte , onde você verá que a lista de argumentos paraprintf
é uma lista vinculada alocada dinamicamente e também que não está sendo usadaexecve()
para executarprintf
(que é o que limita o comprimento de uma lista de argumentos ao executar um utilitário externo).Um exemplo de shell onde
printf
não é um utilitário embutido é oksh
shell do OpenBSD. O utilitário também pode ser desabilitado nobash
uso doenable -n printf
.Esse não é o limite de um shell , mas um limite do sistema operacional (do kernel Linux), especificamente de sua
execve(2)
syscall, e causado pela maneira antiquada como os argumentos da linha de comando e as variáveis de ambiente são passados para um programa iniciado.(Observe que esse limite também inclui as variáveis de ambiente!).
Como os shells internos não passam
execve(2)
, eles não precisam ter nenhum limite como esse. O shell moderno geralmente não usa buffers de tamanho fixo e tal, então o limite geralmente é imposto pela quantidade de memória disponível e o layout do espaço de endereço virtual - ou seja, é ilimitado para todos os efeitos.O padrão POSIX requer que o shell seja implementado sem limite de linha.
Portanto, esta é uma naturalidade que as conchas não documentam.
BTW: devido a esse fato, um script de shell pode não ser um arquivo de texto, pois um arquivo de texto é um arquivo que não possui linhas maiores que LINE_MAX ;-)