bash while loop que quebra em um determinado tamanho de arquivo

3

Então, eu comprei este livro chamado Primes e Programming , e é bem difícil. Hoje eu escrevi este programa (simples) do capítulo 1:

#!/usr/bin/env python

import math

def find_gcd(a,b):
    while b > 0:
        r = a - b * math.floor(a/b)
        a = b
        b = r
    return int(a)

if __name__ == "__main__":
    import random, sys
    while True:
        print find_gcd(random.randrange(int(sys.argv[1])), random.randrange(int(sys.argv[2])))

... e agora eu chamei assim:

./gcd-rand.py 10000 10000 > concievablyreallyhugefile

... e agora eu estou sonhando com um bash one-liner que quebra quando o arquivo atinge um certo tamanho. Eu acho que seria algo parecido com:

while $(du -h f) < 32M; do ./gcd-rand.py 10000 10000 > $f; done

... mas eu nunca escrevi um loop while em bash antes e realmente não sei como a sintaxe funciona.

    
por ixtmixilix 07.03.2013 / 12:20

4 respostas

3

./gcd-rand.py 10000 10000 | head -c 32M > concievablyreallyhugefile

head irá parar de ler após 32MB. Logo depois que head parar de ler, gcd-rand.py receberá um SIGPIPE sinaliza e sai.

Para evitar o armazenamento de uma última linha truncada, como Michael Kjörling notou:

./gcd-rand.py 10000 10000 | head -c 32M | sed '$d' > concievablyreallyhugefile
    
por 08.03.2013 / 01:52
2

O truque é usar o comando de teste test ou o equivalente [ ... ] :

 while [ "$(du -m f|cut -f1)" -lt 32 ]
 do 
  ./gcd-rand.py 10000 10000 > "$f"
 done

Veja help test para mais informações.

Nota

O comando

test ou [ é um bash incorporado . As informações de ajuda podem ser recuperadas no bash via help test ou help [ . man test refere-se ao comando test que é usado se um shell não tiver tal builtin ou for chamado explicitamente como /usr/bin/test .

    
por 07.03.2013 / 12:39
1

Seu código python faz um loop para sempre. Assim, você pode querer executá-lo em segundo plano e, em seguida, eliminá-lo quando o tamanho do arquivo for excedido. Como uma linha:

{ ./gcd-rand.py 10000 10000 > f & }; p=$!; while (( $(stat -c %s f) < 33554432 )); do sleep .1; done; kill $p

Nota: escolha o tempo de sono conforme apropriado, em vez de stat, você também pode usar du, como sugerido por Dirk.

    
por 07.03.2013 / 14:33
0

Você pode usar o comando ulimit para restringir o tamanho de um arquivo que o shell (ou seus filhos) pode criar:

ulimit -f 32768
    
por 09.03.2013 / 23:43