Um script para copiar pastas aleatórias

6

Eu gostaria de realizar um pequeno projeto que sempre tive em mente. Eu tenho uma vasta biblioteca de músicas na minha área de trabalho e estou procurando uma maneira / script para selecionar uma quantidade aleatória de pastas (digamos, 25 álbuns) e, se possível, copiá-las em uma unidade USB para o meu carro. Minha visão completa seria um script capaz de seguir estes passos:

  1. Apague o drive USB (ele seria usado apenas para música)
  2. Seleção aleatória de álbuns (limite de quantidade de dados? número fixo?)
  3. Copie a seleção para a unidade USB

Isso é possível através de um script simples? Eu lembro que alguns organizadores de música tinham essa opção, mas eu estava procurando por algo mais simples para um servidor sem cabeçalho.

    
por Seb 23.05.2016 / 12:02

3 respostas

7

você pode usar find e shuf:

#!/bin/bash

SOURCE="path/to/source"
DESTINATION="path/to/destination"
COUNT=25

rm -r "${DESTINATION}/"*
find "$SOURCE" -mindepth 2 -maxdepth 2 -type d|shuf -n $COUNT|xargs -d'\n' -I{} cp -r "{}" "$DESTINATION"
    
por user448115 23.05.2016 / 14:36
7

O script abaixo deve fazer o trabalho:

#!/usr/bin/env python3
import random
import os
import subprocess
import shutil

# set the desired number of folders to pick below
n_selection = 5
# set the name of the flash drive below
flashdr = "Lexar"
# set the source directory (with media folders) below
sourcedr = "/path/to/mediafiles"
# ---

try:
    targetdr = [l.split("part ")[-1] for l in subprocess.check_output("lsblk")\
                .decode("utf-8").splitlines()if l.endswith(flashdr)][0]
except IndexError:
    pass
else:
    # empty the flash drive
    for item in os.listdir(targetdr):
        obj = os.path.join(targetdr, item)
        try:
            shutil.rmtree(obj)
        except NotADirectoryError:
            os.remove(obj)
    # list the source dirs
    srclist = []
    for dr in  os.listdir(sourcedr):
        fullpath = os.path.join(sourcedr, dr)
        if os.path.isdir(fullpath):
            srclist.append([dr, fullpath])
    # copy the files
    for picked in random.sample(srclist, n_selection):
        shutil.copytree(picked[1], os.path.join(targetdr, picked[0]))
        srclist.remove(picked)

Copia diretórios do primeiro subnível do diretório de origem para o flash drive desejado.

Isto é o que parece fazer mais sentido, uma vez que recursivamente copiando pastas, aleatoriamente , causa uma grande diferença em sub-níveis de tamanho de pasta e número. Eu adicionei, no entanto, como uma segunda opção na parte inferior desta resposta.

Como usar

  1. Copie o script em um arquivo vazio, salve-o como create_mediausb.py
  2. Na seção head, defina o número de arquivos a serem selecionados, o nome da unidade flash (o script encontrará seu caminho) e o di-reitor de origem com pastas.
  3. Execute o script com o comando:

    python3 /path/to/create_mediausb.py 
    
  4. Se tudo funcionar bem, adicione-o a uma tecla de atalho: escolha: Configurações do sistema > "Teclado" > "Atalhos" > "Atalhos personalizados". Clique no botão "+" e adicione o comando:

    python3 /path/to/create_mediausb.py 
    

Segunda opção: seleção recursiva

#!/usr/bin/env python3
import random
import os
import subprocess
import shutil

n_selection = 5
flashdr = "Lexar"
sourcedr = "/home/jacob/Bureaublad/GW_site_nafestival_2015/pix/general"

try:
    targetdr = [l.split("part ")[-1] for l in subprocess.check_output("lsblk")\
                .decode("utf-8").splitlines()if l.endswith(flashdr)][0]
except IndexError:
    pass
else:
    # empty the flash drive
    for item in os.listdir(targetdr):
        obj = os.path.join(targetdr, item)
        try:
            shutil.rmtree(obj)
        except NotADirectoryError:
            os.remove(obj)
    # list the source dirs
    srclist = []
    for root, dirs, files in os.walk(sourcedr):
        for dr in dirs:
            srclist.append([dr, os.path.join(root, dr)])
    # copy the files
    for picked in random.sample(srclist, n_selection):
        shutil.copytree(picked[1], os.path.join(targetdr, picked[0]))
        srclist.remove(picked)

O script:

  1. Procura o caminho para o pen drive:

    try:
        targetdr = [l.split("part ")[-1] for l in subprocess.check_output("lsblk")\
                    .decode("utf-8").splitlines()if l.endswith(flashdr)][0]
    except IndexError:
        pass
    

    Se a unidade flash não for encontrada, ela terminará aqui

  2. Se a unidade foi encontrada, ela é esvaziada

    # empty the flash drive
    for item in os.listdir(targetdr):
        obj = (targetdr+"/"+item)
        try:
            shutil.rmtree(obj)
        except NotADirectoryError:
            os.remove(obj)
    
  3. Então, como precisamos da lista de diretórios para fazer uma seleção apropriada aleatoriamente, criamos uma lista antes de fazer a seleção:

    # list the source dirs
    srclist = []
    for dr in  os.listdir(sourcedr):
        fullpath = sourcedr+"/"+dr
        if os.path.isdir(fullpath):
            srclist.append([dr, fullpath])
    
  4. A parte mais interessante é fazer a seleção. Escolhemos um diretório aleatório, o removemos da lista para evitar escolhas duplas, depois escolhemos outro aleatoriamente, removemos e assim por diante, até alcançarmos o número de escolhas desejadas:

    # copy the files
    for picked in random.sample(srclist, n_selection):
        shutil.copytree(picked[1], os.path.join(targetdr, picked[0]))
        srclist.remove(picked)
    
por Jacob Vlijm 23.05.2016 / 14:03
1

Eu fiz um script com o Python:

O script, no GitHub Gist. ( Transferir )

Uso:

python3 RandomCopier.py [source folder] [destination folder] [number to copy]

O método de cópia:

OBSERVAÇÃO: Ele não copiará os arquivos diretamente na pasta de origem, somente aqueles em subpastas.

Diga, a pasta de origem, src is:

src
|- a
|  |- file_a
|  |- file_a_2
|
|- b
|  |- file_b
|
|- c
|  |- file_c
|
|- file_src

então, a pasta de destino dest seria, com 2 pastas copiadas aleatoriamente, como:

dest
|- a
|  |- file_a
|  |- file_a_2
|
|- c
|  |- file_c
    
por UniversallyUniqueID 23.05.2016 / 13:57