Como selecionar uma amostra aleatória de n linhas de cada arquivo em um diretório

0

Eu tenho um diretório com muitos arquivos. De cada um desses arquivos, eu quero uma amostra aleatória e copio para um novo diretório com nomes de arquivos iguais aos do qual uma amostra aleatória foi desenhada.

    
por Abhishek Gupta 17.04.2018 / 18:11

1 resposta

0

mkdir -p random_samples
find dir -type f -exec sh -c 'for n do sort -R "$n" | head >"random_samples/${n##*/}"; done' sh {} +

Isso irá procurar por todos os arquivos regulares dentro ou abaixo de dir e executará um breve script de shell sobre estes:

for n do
    sort -R "$n" | head >"random_samples/${n##*/}"
done

Este script de shell curto fará um loop sobre os nomes de caminho fornecidos (que serão arquivos regulares encontrados por find ) e executará sort -R em cada um deles. Isso irá misturar as linhas, e o head produzirá as dez primeiras linhas de cada aleatório. A saída irá para o diretório random_samples com um nome de arquivo igual ao arquivo original. Nenhuma verificação de colisões de nome de arquivo em random_samples está concluída.

Em vez de sort -R , você também pode usar shuf do GNU coreutils.

A única desvantagem é que a ordenação das linhas nas amostras aleatórias será aleatória, isto é, as linhas nas amostras aleatórias não serão ordenadas de acordo com a ordenação original no arquivo.

Para impor a mesma ordem nas amostras aleatórias, como no arquivo original, podemos substituir nosso script de shell curto por

for n do
    awk -v OFS="\t" "{ print NR, \
find dir -type f -exec sh -c '
    for n do
        awk -v OFS="\t" "{ print NR, \
mkdir -p random_samples
find dir -type f -exec sh -c 'for n do sort -R "$n" | head >"random_samples/${n##*/}"; done' sh {} +
}" "$n" | sort -R | head | sort -n | cut -f 2 >"random_samples/${n##*/}" done' sh {} +
}" "$n" | sort -R | head | sort -n | cut -f 2 >"random_samples/${n##*/}" done

Isso começa com o acréscimo de cada linha do arquivo com seu número de linha (e uma tabulação) e, em seguida, embaralha as linhas e escolhe as 10 primeiras como antes. Em seguida, as linhas selecionadas são classificadas numericamente e os números de linha são removidos antes que a amostra seja salva.

Permitindo que find execute isso:

for n do
    sort -R "$n" | head >"random_samples/${n##*/}"
done

Para escolher mais ou menos de 10 linhas, altere head para head -n NUM , em que NUM é o número desejado de linhas a serem escolhidas.

    
por 17.04.2018 / 18:46