IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Script complexe de recopie de fichiers


Sujet :

Shell et commandes GNU

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2008
    Messages
    764
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2008
    Messages : 764
    Par défaut Script complexe de recopie de fichiers
    Bonjour,

    Je tourne sur linux.

    Je désire couper coller des fichiers qui se trouvent dans un dossier recup vers plusieurs dossiers que le script doit créer automatiquement en indexant le nom.
    je désire aussi que ces fichiers soient coupés par tranche de 1500. Lorsque 1500 fichiers ont été copiés dans le dossier de destination, le script doit créer un nouveau dossier en indexant le nom (+ 1) et recommencer une coupe des 1500 fichiers suivants.

    En gros cela consiste à morceler un dossiers en plusieurs sous dossiers car le dossier recup contient plus de 150 000 fichiers et c'est très lent (plusieurs heures) pour faire des opérations à la souris.

    voici ce que j'ai fait mais qui ne fonctionne pas (il me faut aussi modifier la commande cp par la commande mv) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    total=0;
    fileName = "savedJpg";
    cpt = 1;
    cd /home/gericojo/recup/output/jpg;
     
    for i in {1..1500}; do
        for fichier in *.jpg; do
            cp "$fichier" /home/gericojo/
            cpt = cpt + 1
            fileName = fileName + cpt
            mkdir fileName
            break
        done;
    done;
     
    exit 0
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    gericojo@gericojo-Satellite-A300:~$ bash scr2.sh
    scr2.sh: ligne 2: fileName : commande introuvable
    scr2.sh: ligne 3: cpt : commande introuvable
    Merci à vous si vous voulez bien m'aider !

  2. #2
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 652
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 652
    Par défaut
    Bonjour,

    B A BA de l'écriture de scripts :
    • disposer d'un interpréteur de commande.
    • lire l'ABS, et/ou, au moins, un des tutoriels qui figure dans ma signature, en commençant par le début, à savoir l'assignation de variables.

    et puis un peu d'algorithmique... visualise la manière de faire "à la main".
    par exemple (en pseudo-code) :
    • destination = 1
    • je copie un fichier
    • si nbFichiers +1 = 1500; alors nbFichiers = 0; destination = +1; finsi
    • je copie un fichier
    • si nbFichiers +1 = 1500; alors nbFichiers = 0; destination = +1; finsi
      ...
    évidemment, ce sera mieux dans une boucle !
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    je sais pas si c'est moi qui suis fatigué mais j'ai trouvé l'exercice moins simple qu'il y paraissait, pour peu qu'on se soucie des espaces éventuels dans les noms de fichiers et qu'on tente de minimiser le nombre d'appels à mv

    du coup j'ai pas mieux que ça, c'est assez crado dans l'idée, mais ça marche au poil :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #!/bin/bash
     
    SRC="recup"
    DST="destination"
    MAXF=15
     
    counter=0
    while true; do
       liste=$(find ${SRC}/ -type f -printf "\\\\\"%p\\\\\"\n" | head -n${MAXF} | xargs)
       mkdir -p "${DST}/${counter}"
       echo "mv ${liste} ${DST}/${counter}/" | bash 2>/dev/null || break
    #  echo "${DST}/${counter}/ : ${liste}"
       let counter++
    done
     
    rmdir "${DST}/${counter}/"
    l'astuce consiste à construire de toute pièce la ligne d'invocation et notamment la liste de noms de fichiers du style "fichier1" "fichier2" "fichier3 avec des espaces" etc.
    l'autre astuce consistant à sortir de la boucle while lorsque mv se vautre, et à effacer le dernier répertoire créé (vide) avant de terminer le script

    et l'exécution (avec MAXF=3 pour plus de lisibilité) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ mkdir -p recup destination
    $ touch recup/fichier\ numero\ {1..100}
    $ chmod 750 ./pouet.sh
    $ ./pouet.sh
    destination/0/ : "recup/fichier numero 60" "recup/fichier numero 59" "recup/fichier numero 34"
    destination/1/ : "recup/fichier numero 80" "recup/fichier numero 8" "recup/fichier numero 93"
    destination/2/ : "recup/fichier numero 13" "recup/fichier numero 31" "recup/fichier numero 6"
    (...)
    destination/31/ : "recup/fichier numero 27" "recup/fichier numero 96" "recup/fichier numero 95"
    destination/32/ : "recup/fichier numero 50" "recup/fichier numero 32" "recup/fichier numero 89"
    destination/33/ : "recup/fichier numero 16"

  4. #4
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 652
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 652
    Par défaut
    j'ai pensé proposer l'utilisation d'un tableau, dont on aurait copié les éléments par groupes de 1500, mais
    - les commandes acceptent une liste d'arguments d'une longueur limitée (1500 * n_caractères, c'est pas trop?).
    - la mémoire nécessaire à un éventuel déplacement sur un autre système de fichiers peut ne pas être suffisante.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  5. #5
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 120
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 120
    Par défaut
    Salut,

    et pour ta culture personnelle concernant tes 2 messages d'erreur,
    Citation Envoyé par francky74 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
            cpt = cpt + 1
            fileName = fileName + cpt
            mkdir fileName
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    gericojo@gericojo-Satellite-A300:~$ bash scr2.sh
    scr2.sh: ligne 2: fileName : commande introuvable
    scr2.sh: ligne 3: cpt : commande introuvable
    !
    quand on veut utiliser une variable en lecture, il faut lui rajouter $ devant. Oui c'est tordu mais c'est comme ça...
    Et on protège toujours (sinon on se fait crier dessus ) ses variables par des doubles quotes (sauf pour des calculs, voir ci-dessous).
    Donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
            cpt = $(($cpt + 1)) # syntaxe compliquée, pour faire des calculs
            fileName = "$fileName" + "$cpt"
            mkdir "$fileName"
    Par ailleurs, avec ton histoire de concaténation (fileName = "$fileName" + "$cpt"), tu risques de te retrouver avec des drôles de noms de fichiers...
    Fais donc un simple test dans une console avec juste
    cpt=0; fileName="test"; for i in {1..3}; do cpt=$(($cpt+1)); fileName="$fileName"+"$cpt"; echo $fileName; done
    à copier/coller, et réfléchis

    Sinon, les copains t'ont proposé d'autres solutions, à toi de voir.

  6. #6
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 347
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 347
    Par défaut
    Bonjour,

    @jipété: l'erreur est surtout situé sur la déclaration de variables (espace en trop autour du signe "=")

    Sinon, personnellement, je serais passé par find + awk:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find . -type f -printf "%p\n" | awk -vfnb=3 -vdfn=5 'BEGIN{MAXF=-1;MULTI=-1;cnt=-1};{STR=STR" \\\""$0"\\\""};++MAXFR % fnb == 0 && ++MULTI % dfn == 0 {cnt++;system("echo mkdir -p destination/"cnt)};MAXFR % fnb {next}{system( "echo mv "STR" destination/"cnt"/");STR=""}'
    Bon dans cet exemple, je ne fais que des echo des commande "mv" et "mkdir".
    L'idée ici, est de déplacer n fichier à la fois (-vfnb=3) et de refaire cette action n fois (-vdfn=5) avant de créer et utiliser un nouveau répertoire (il faut donc que le nb de fichiers par répertoire soit fnb*dfn).
    Ici, ce n'est qu'un exemple, il faut réagencer la ligne pour qu'elle prenne en compte des variables pour la source et la destination. Il faudrait aussi rajouter le bloc END pour traiter les derniers fichiers résiduels.

    Sinon, on doit pouvoir passer à mv les 1500 fichiers à déplacer en une seule fois, il faut juste, me semble-t-il, utiliser une syntaxe multiligne...
    Mais je ne peux pas le confirmer

Discussions similaires

  1. création script korn shell de recopie de fichiers
    Par jeje4 dans le forum Shell et commandes GNU
    Réponses: 3
    Dernier message: 29/03/2007, 07h38
  2. Script d'envoie d'un fichier excel via un formulaire
    Par Morphine.Nw dans le forum ASP
    Réponses: 4
    Dernier message: 26/01/2006, 13h08
  3. Réponses: 1
    Dernier message: 19/01/2006, 19h22
  4. Script MSDOS de purge de fichier
    Par tilb dans le forum Windows
    Réponses: 1
    Dernier message: 12/01/2006, 13h12
  5. Script shell - écriture dans un fichier
    Par Leishmaniose dans le forum Linux
    Réponses: 6
    Dernier message: 13/12/2004, 22h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo