Existe algum tipo de limite de caractere imposto no bash (ou outros shells) por quanto tempo uma entrada pode ter? Em caso afirmativo, qual é o limite de caracteres?
Ou seja, é possível escrever um comando em bash que seja muito longo para a linha de comando ser executado? Se não houver um limite obrigatório, existe um limite sugerido?
bash
shell
unix
command-line-arguments
Derek Halden
fonte
fonte
Respostas:
O limite para o comprimento de uma linha de comando não é imposto pelo shell, mas pelo sistema operacional. Esse limite geralmente está na faixa de cem kilobytes. POSIX denota este limite
ARG_MAX
e em sistemas compatíveis com POSIX, você pode consultá-lo com$ getconf ARG_MAX # Get argument limit in bytes
Por exemplo, no Cygwin é 32000, e nos diferentes sistemas BSDs e Linux que eu uso é de 131072 a 2621440.
Se você precisa processar uma lista de arquivos que excedem esse limite, pode dar uma olhada no
xargs
utilitário, que chama um programa repetidamente com um subconjunto de argumentos que não excedeARG_MAX
.Para responder à sua pergunta específica, sim, é possível tentar executar um comando com uma lista de argumentos muito longa. O shell irá apresentar um erro com uma mensagem ao longo da "lista de argumentos muito longa".
Observe que a entrada para um programa (conforme lida em stdin ou qualquer outro descritor de arquivo) não é limitada (apenas por recursos de programa disponíveis). Portanto, se seu script de shell lê uma string em uma variável, você não está restrito por
ARG_MAX
. A restrição também não se aplica a shell-builtins.fonte
cmd <<< "$LONG_VAR"
obtiver uma construção e o valor LONG_VAR exceder o limite, meu comando explodirá?LONG_VAR
é passado para stdin - e isso é feito inteiramente no shell; não é expandido como um argumento paracmd
, então o limite ARG_MAX para fork () / exec () não entra em jogo. É fácil tentar você mesmo: crie uma variável com conteúdo superior a ARG_MAX e execute seu comando.blah="$(cat /home/schwager/Music/Recordings/20090420\ 131623.m4a)"; cat <<< $blah >/dev/null
. Observe nenhum erro.xargs
no MacOS 10.12.6 limites quanto ele tenta colocar em umexec()
aARG_MAX - 4096
. Portanto, o uso de scriptsxargs
pode funcionar, até que um dia alguém coloque muita coisa no ambiente. Correndo para isso agora (contorne isso comxargs -s ???
:).Ok, habitantes. Portanto, já há algum tempo aceitei os limites de comprimento de linha de comando como verdade. Então, o que fazer com as suposições de alguém? Naturalmente, verifique-os.
Tenho uma máquina Fedora 22 à minha disposição (ou seja: Linux com bash4). Eu criei um diretório com 500.000 inodes (arquivos) em cada um de 18 caracteres. O comprimento da linha de comando é de 9.500.000 caracteres. Criado assim:
seq 1 500000 | while read digit; do touch $(printf "abigfilename%06d\n" $digit); done
E notamos:
No entanto, posso fazer isso:
$ echo * > /dev/null
Mas isso falha:
$ /bin/echo * > /dev/null bash: /bin/echo: Argument list too long
Posso executar um loop for:
$ for f in *; do :; done
que é outro shell embutido.
Leitura cuidadosa da documentação para
ARG_MAX
estados, comprimento máximo do argumento para as funções exec . Isso significa: Sem chamarexec
, não háARG_MAX
limitação. Portanto, isso explicaria por que os builtins do shell não são restritos porARG_MAX
.E, de fato, posso conseguir
ls
meu diretório se minha lista de argumentos tiver 1.09948 arquivos ou cerca de 2.089.000 caracteres (mais ou menos). Depois de adicionar mais um arquivo de nome de arquivo de 18 caracteres, no entanto, recebo um erro Lista de argumentos muito longa . Portanto,ARG_MAX
está funcionando conforme anunciado: o exec está falhando com mais deARG_MAX
caracteres na lista de argumentos - incluindo, deve-se observar, os dados do ambiente.fonte
for f in *; do echo $f; done
não bifurca (todos os builtins). Portanto, não sei se um combo find-xargs será mais rápido; não foi testado. Na verdade, não sei qual é o conjunto de problemas do OP. Talvezfind /path/to/directory
não seja útil para ele porque retornará o nome do caminho do arquivo. Talvez ele goste da simplicidade de umfor f in *
loop. Independentemente disso, a conversa é sobre limite de entrada de linha - não eficiência. Portanto, vamos continuar no tópico, que diz respeito ao comprimento da linha de comando.Existe um limite de buffer de algo como 1024. A leitura irá simplesmente travar no meio da colagem ou da entrada. Para resolver isso, use a opção -e.
http://linuxcommand.org/lc3_man_pages/readh.html
-e use Readline para obter a linha em um shell interativo
Mude sua leitura para ler -e e a interrupção da entrada de linha irritante vai embora.
fonte
read
: "Ou seja, é possível escrever um comando no bash que seja muito longo para a linha de comando ser executado?"bash --noediting
, e no novo prompt tente executar o comandoecho somereallylongword
, onde alguma palavra realmente longa tem mais de 4090 caracteres. Tentei no Ubuntu 18.04, a palavra ficou truncada, então obviamente isso tem algo a ver com Readline não estar habilitado.