web-dev-qa-db-fra.com

Un script pour copier des dossiers aléatoires

J'aimerais réaliser un petit projet auquel j'ai toujours pensé. J'ai une vaste bibliothèque de musique sur mon bureau et je cherche un moyen/script pour sélectionner un nombre aléatoire de dossiers (disons 25 albums) et, si possible, les copier sur une clé USB pour ma voiture. Ma vision complète serait un script capable de faire ces étapes:

  1. Effacer le lecteur USB (il ne serait utilisé que pour la musique)
  2. Sélection aléatoire d'albums (limite de quantité de données? Nombre fixe?)
  3. Copier la sélection sur le lecteur USB

Est-ce faisable via un script simple? Je me souviens que certains organisateurs de musique avaient cette option, mais je cherchais quelque chose de plus simple pour un serveur sans tête.

6
Seb

Le script ci-dessous devrait faire le travail:

#!/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)

Il copie les répertoires du premier sous-niveau du répertoire source dans le lecteur flash ciblé.

C'est ce qui semble le plus logique, puisque de manière récurrente la copie de dossiers, au hasard, provoque une grande différence de sous-niveaux de taille et de nombre de dossiers. Je l'ai néanmoins ajouté comme deuxième option au bas de cette réponse.

Comment utiliser

  1. Copiez le script dans un fichier vide, enregistrez-le sous le nom create_mediausb.py
  2. Dans la section head, définissez le nombre de fichiers à sélectionner, le nom du lecteur flash (le script trouvera son chemin) et le répertoire source avec les dossiers.
  3. Exécutez le script avec la commande:

    python3 /path/to/create_mediausb.py 
    
  4. Si tout fonctionne correctement, ajoutez-le à une touche de raccourci: choisissez: Paramètres système> "Clavier"> "Raccourcis"> "Raccourcis personnalisés". Cliquez sur le "+" et ajoutez la commande:

    python3 /path/to/create_mediausb.py 
    

Deuxième option: sélection récursive

#!/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)

Le scénario:

  1. Cherche le chemin du lecteur flash:

    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
    

    Si le lecteur flash n'est pas trouvé, il se termine ici

  2. Si le lecteur a été trouvé, il est vidé

    # empty the flash drive
    for item in os.listdir(targetdr):
        obj = (targetdr+"/"+item)
        try:
            shutil.rmtree(obj)
        except NotADirectoryError:
            os.remove(obj)
    
  3. Ensuite, puisque nous avons besoin de la totalité liste de répertoires pour faire une sélection appropriée au hasard, nous créons une liste avant de faire la sélection:

    # list the source dirs
    srclist = []
    for dr in  os.listdir(sourcedr):
        fullpath = sourcedr+"/"+dr
        if os.path.isdir(fullpath):
            srclist.append([dr, fullpath])
    
  4. La partie la plus intéressante est la sélection. Nous sélectionnons un répertoire au hasard, le supprimons de la liste pour éviter les doubles choix, puis en sélectionnons un autre au hasard, le supprimons, etc. jusqu'à atteindre le nombre de choix souhaité:

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

vous pouvez utiliser find et 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"
7
user448115

J'ai fait un script avec Python:

Le script, sur GitHub Gist. ( Télécharger )

Utilisation:

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

La méthode de copie:

REMARQUE: Il va not ​​copier tous les fichiers directement dans le dossier source, uniquement ceux qui se trouvent dans des sous-dossiers.

Disons que le dossier source, src est:

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

alors, le dossier de destination dest serait, avec 2 dossiers copiés aléatoirement, comme:

dest
|- a
|  |- file_a
|  |- file_a_2
|
|- c
|  |- file_c
1