Como copiar arquivos aleatórios para uma pasta específica?

3

Eu tenho uma vasta coleção de arquivos (6,5 milhões) em várias pastas e sub-pastas e eu quero copiar algumas escolhas aleatórias (cerca de 200k-300k arquivos) para um diretório para fazer uma amostra aleatória.

a árvore de pastas é esta (apenas uma pequena amostra) dentro de cada pasta existem vários arquivos

.
├── articles.0-9A-B.txt
│   ├── 20_Century_Br_Hist
│   ├── 3_Biotech
│   ├── A_A_Case_Rep
│   ├── AAPS_J
│   ├── AAPS_PharmSciTech
│   ├── Abdom_Imaging
│   ├── Abdom_Radiol
│   ├── Abdom_Radiol_(NY)
│   ├── Acad_Emerg_Med
│   ├── Acad_Med
│   ├── Acad_Psychiatry
│   ├── Acad_Radiol
│   ├── Acc_Chem_Res
.
.
.
│   ├── Bull_Sci_Technol_Soc
│   ├── Bull_Volcanol
│   ├── Bull_World_Health_Organ
│   ├── Bundesgesundheitsblatt_Gesundheitsforschung_Gesundheitsschutz
│   ├── Burn_Res
│   ├── Burns
│   ├── Burns_Trauma
│   └── Bus_Soc
├── articles.A-B.xml
│   ├── 20_Century_Br_Hist
│   ├── 3_Biotech
│   ├── A_A_Case_Rep
│   ├── AAPS_J
│   ├── AAPS_PharmSciTech
│   ├── Abdom_Imaging
.
.
.
    
por mejillonius 17.11.2017 / 12:58

1 resposta

4

Normalmente isso seria um oneliner, mas pode ser uma má idéia processar um número tão grande de arquivos (name) s diretamente, então vou usar um arquivo temporário aqui.

#!/bin/bash
a=$(mktemp)
find /path/to/dir -type f | shuf -n $(shuf -i200000-300000 -n1) >$a
while IFS='' read -r l || [[ -n "$l" ]]; do
    cp "$l" /path/to/out/dir
done <$a

Isso localizará todos os arquivos localizados em /path/to/dir , embaralhe-os e salve um número aleatório de linhas (entre 200.000 e 300.000, conforme solicitado) da saída em tempfile $a . O while loop apenas copia todos os arquivos da lista para /path/to/out/dir .

Bobagem, não precisamos de um arquivo temporário, apenas passamos para o loop while ou - o que eu prefiro - para tr e xargs :

#!/bin/bash
find /path/to/dir -type f | shuf -n $(shuf -i200000-300000 -n1) |\
tr '\n' '
#!/bin/bash
a=$(mktemp)
find /path/to/dir -type f | shuf -n $(shuf -i200000-300000 -n1) >$a
while IFS='' read -r l || [[ -n "$l" ]]; do
    cp "$l" /path/to/out/dir
done <$a
' | xargs -0 -n1 cp -t /path/to/out/dir

Dessa forma, você pode especificar quantos nomes de arquivos cada invocação de cp deve receber por meio da opção xargs ' -n .

    
por dessert 17.11.2017 / 13:43