Ajuda com inteiros de 64 bits em scripts?

2

Talvez eu esteja pensando demais nisso (embora eu não pense que sou) ... ou talvez haja uma forma mais simples de resolver meu problema?

Eu tenho uma exigência de que, se um arquivo for maior que 1 GB, ele será dividido em partes menores para processamento.

Nenhum problema até agora, que pode ser facilmente alcançado com o dd.

O problema é o que acontece com arquivos maiores que 4GB?

Meu pensamento no momento é começar pelas seguintes linhas ...

# Determine if file needs to be split
determineSplit() {
    typeset FILE_SIZE=$(ls -l "${1}" | awk '{print $5}');
    typeset -F NUMBER_OF_GIGS=$(print "${FILE_SIZE}/${BK_ONEGIG}"|bc) # using bc for >4GB
    if (( ${NUMBER_OF_GIGS} >= 1 )); then
        return 0
    else
        return 1
    fi
}

Depois que a necessidade de dividir é determinada, eu sei que preciso chamar dd em um loop ... mas o problema é, o que eu faço sobre o cálculo de pontos de busca para dd se eu não posso usar números inteiros de 64 bits declarações condicionais ksh?

Estou toda confusa!

Editar para esclarecer: (1) Eu estou esperando fazer um script razoavelmente portátil, então de preferência não há respostas GNU-only (2) Não, split não funcionará por razões descritas no meu comentário abaixo; -)

    
por user119886 10.01.2014 / 19:21

2 respostas

0

Você deve procurar split ; pode fazer o que quiser. (Também, como observa @Marco em seu comentário, não analise ls output; considere usar stat -f '%s' ) Se não:

Você não precisa calcular pontos de busca, deixe o descritor de arquivos fazer isso para você. Esta é a sintaxe do bash:

for ((i = 0; i < n_blocks; ++i); do
    dd bs=4k count=262144
done < "input-file-name"

O ponto chave é deixar o arquivo de entrada aberto como stdin de dd , então cada vez que dd ler, ele continuará de onde parou.

    
por 10.01.2014 / 19:35
0

ATT ksh93, bash e dash (mas não pdksh ou mksh) e pelo menos algumas configurações do BusyBox suportam aritmética de 64 bits mesmo em plataformas de 32 bits.

Você não precisa de aritmética de shell de 64 bits, desde que seus arquivos não sejam maiores que 4EB. Chame bc de uma vez por todas para contar o número de blocos de 1GB no arquivo e, em seguida, chame dd uma vez por bloco.

typeset size=$(ls -log -- "${1}" | awk 'NR==1 {print $3}')
typeset blocks=$(echo "($size - 1) / 1073741824" | bc)
typeset -i b
for ((b = 0; b < blocks; b++)); do
  dd if="$1" bs=1073741824 skip=$b | …
done

Como alternativa, você pode chamar dd em um loop, com todo o loop lendo do arquivo. A dificuldade é perceber quando a entrada está vazia; dd informa sobre seu erro padrão.

while
  case "$({ LC_ALL=C dd bs=1048576 count=1024 2>&3 | … 1>&4; } 3>&1)" in
    '0+0 records in'*) false;;
  esac
do
  :
done <"$1" 4>&1

Se o tamanho do arquivo for um múltiplo exato do tamanho do bloco, o aplicativo será executado com um arquivo vazio na última vez. Isso parece difícil de evitar; uma solução desajeitada seria ler o próximo byte, embora tenha cuidado, pois, se você o ler em uma variável shell, precisará tomar cuidado para que, se for um byte nulo, você receba uma string vazia.

    
por 11.01.2014 / 03:11