AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 719281
Accepted
DEKKER
DEKKER
Asked: 2022-10-01 04:20:46 +0800 CST2022-10-01 04:20:46 +0800 CST 2022-10-01 04:20:46 +0800 CST

Maneira mais rápida de escrever variável bash em um arquivo

  • 772

Eu quero gerar alguns arquivos grandes para algum experimento.

Este é o meu roteiro. Ele cria um arquivo, em seguida, o lê para uma variável e tenta escrevê-lo quantas vezes forem definidas no loop em arquivos:

#! /usr/bin/env bash

set -e
set -u

< /dev/urandom tr -dc "\t\n [:alnum:]" | head -c32768 > temp.txt
data=$(cat ./temp.txt)

for testdir in "$@"; do
    echo "create directory '$testdir'"
    mkdir -p $testdir
    for i in {1..3}; do
        counter=$(printf %02d $i)
        testfile=$testdir/test_${testdir##*/}_$counter.txt
        echo "create file '$testfile'"
        echo "$data" > $testfile
    done
done

Se eu tentar usar este script para criar 3000 arquivos (cada pasta terá 3 arquivos) demora cerca de 19s no meu sistema:

tempo generateUserData.sh TESTE{0..1000}

create directory 'TEST999'
create file 'TEST999/test_TEST999_01.txt'
create file 'TEST999/test_TEST999_02.txt'
create file 'TEST999/test_TEST999_03.txt'
create directory 'TEST1000'
create file 'TEST1000/test_TEST1000_01.txt'
create file 'TEST1000/test_TEST1000_02.txt'
create file 'TEST1000/test_TEST1000_03.txt'

real    0m19.333s
user    0m14.791s
sys     0m4.784s

O reconhecimento echopode ser a parte lenta aqui. Alguma ideia de como posso fazer o dele o mais rápido possível?

bash shell-script
  • 2 2 respostas
  • 90 Views

2 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2022-10-01T04:51:06+08:002022-10-01T04:51:06+08:00

    O que seria lento seria bifurcar processos e executar comandos externos comomkdir

    counter=$(printf %02d $i)
    

    Também bifurca um processo no bash. Isso pode ser evitado escrevendo-o como:

    printf -v counter %02d "$i"
    

    Ou:

    printf -v testfile %s/%s_%02d.txt "$testdir" "${testdir##*/}" "$i"
    

    Crie todo o diretório com uma mkdirinvocação ( mkdir -p -- "$@"; não esqueça do --) em vez de executar uma mkdirpor arquivo.

    Também não há necessidade de um arquivo temporário:

    data=$(< /dev/urandom tr -dc "\t\n [:alnum:]" | head -c32768; echo .)
    data=${data%.}
    

    A adição de .é necessária se você deseja $datater a garantia de conter 32768 bytes, pois a substituição de comando remove todos os caracteres de nova linha à direita. Observe também que echosem -nadiciona um de volta. printfdeve ser usado em vez de de echoqualquer maneira para dados arbitrários:

    Também tenha cuidado head -c 32768, pois fornece 32768 bytes, não caracteres, portanto, pode cortar caracteres no meio.

    printf %s "$data" > "$file"
    
    • 3
  2. bxm
    2022-10-01T05:37:29+08:002022-10-01T05:37:29+08:00

    Assumindo um pouco do que Stéphane Chazelas disse em sua boa resposta, com alguns ajustes.

    #!/usr/bin/env bash
    
    set -e
    set -u
    
    main() {
      < /dev/urandom tr -dc "\t\n [:alnum:]" | dd iflag=fullblock of=./temp.txt bs=32K count=1
      mkdir -p -- "${@:?}"
      for testdir in "$@"; do
        for i in {1..3}; do
          printf "%s/%s_%02d.txt\n" "$testdir" "${testdir##*/}" "$i"
        done
      done | xargs -n1 -P${proc:-16} cp ./temp.txt
    }
    
    time main "${@}"
    
    
    • dd- maneira alternativa de obter o número exato de bytes (embora isso aconteça apenas uma vez, não fará muita diferença de qualquer maneira)
    • todos aqueles echoadicionados cerca de 3 segundos do meu lado com uma contagem de 1000
    • multithread, ajustável em tempo de execução (via procvariável) - brinque para encontrar o valor ideal para o seu sistema

    por exemplo

    proc=32 bash ./foo.sh {1..1000}
    

    NB - supondo que sua pergunta original sobre o preenchimento da variável fosse uma instância de um problema XY ... se isso for um requisito difícil, minha resposta não é válida conforme escrita.

    Essa alteração deve fazê-lo:

    data="$(< /dev/urandom tr -dc "\t\n [:alnum:]" | dd iflag=fullblock bs=32K count=1)"
    dd iflag=fullblock bs=32K count=1 of=./temp.txt <<<"${data}"
    

    A segunda ddé ter certeza de que obtemos apenas os dados gerados, sem eles, em algum lugar entre $( )e <<<parece que encontramos um byte extra de algum lugar (nova linha implícita?). Feliz em receber correções sobre isso. Parece um pouco complicado, admito, se o tamanho dos dados aleatórios for arbitrário ou sem importância, você pode simplificar isso, tenho certeza

    • 1

relate perguntas

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • MySQL Select com função IN () com array bash

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve