Debian-facile

Bienvenue sur Debian-Facile, site d'aide pour les nouveaux utilisateurs de Debian.

Vous n'êtes pas identifié(e).

#1 04-12-2018 10:42:20

andrea86
Membre
Inscription : 28-11-2018

Un script shell de rangement...

Voilà, après quelques années d'accumulations de fichiers, documents, musique..
J'aimerai profiter de mon come-back sous linux pour faire un peu d'ordre... et qui sait, mettre à profit ce script pour d'autres?

Le problème: un micmac de fichiers dans une arborescence imbriquée n'importe comment accumulés depuis des années...
et l'envie de faire de l'ordre...

Bien sur, je n'aimerai pas qu'on me servent tout sur un plateau d'argent, j'ai quelques idées.:)

1 je cherche à tout mettre dans un seul et unique dossier dans un premier temps, donc une commande mv de déplacement
(ca je sais faire)...  mais pour prendre en compte toute l'arborescence sous-jacente?

2 Après l'idée c'est de mettre chaque types de fichiers dans un répertoire portant le nom de son extension.
(Étant sous windows que j'ai accumulé tout ce fourby, je pense que la quasi totalité des fichiers portent une extension)

Pour ce faire, je pensais :
- lister les fichier du meganouveaurepertoire et pour chaque fichier:
- Récupérer dans dans son nom les derniers caractères après le dernier "."
- Créer pour chaque extension récupérée un répertoire, un dossier.
(avec l'option que lorsqu'un dossier existe déjà, pas besoin de le recréer et d'ecraser le précédent)
(si non il va faire des milliers de fois cette opération pour rien...)

Grossomodo l'idée c'est d'avoir à partir d'une arborescence désordonnée, un dossier père avec des sous-dossier portant le nom de l'extension de son contenu.

Un grand merci d'avance pour votre soutient, et j'espère que ça pourra aider d'autres!

Hors ligne

#2 04-12-2018 11:23:59

kao
Modérateur
Distrib. : Testing
Noyau : Linux 4.quelquechose
(G)UI : Gnome 3
Inscription : 28-09-2012
Site Web

Re : Un script shell de rangement...

Faire du tri est une bonne idée, en automatique c'est un peu plus difficile.

En mélangeant  tout tu risques de perdre des informations que te donnais les dossiers.
Exemple :

/jour1/photo_1.jpg
/jour2/photo_1.jpg



De plus comme ils ont le même nom le deuxieme va écraser le premier. Il faudra trouver une astuce pour les doublons.

Pour le tri, en plus de l'extension tu peux utiliser  les mime-type et faire des classement plus facilement ou différent.

kao@Testing:~$ file --mime-type glx20160911.txt
glx20160911.txt: text/plain
kao@Testing:~$ file --mime-type playlist.m3u
playlist.m3u: text/plain
kao@Testing:~$ file --mime-type Horloge\ pour\ mesurer\ le\ décalage\ image\ son\ 25p.mp4
Horloge pour mesurer le décalage image son 25p.mp4: video/mp4
kao@Testing:~$ file --mime-type Public/
Public/: inode/directory
kao@Testing:~$ file --mime-type test.jpg
test.jpg: image/jpeg


Tiens nous courant de ce que tu as trouvé.

Hors ligne

#3 04-12-2018 12:30:52

phreg
Membre
Distrib. : MX Ubuntu LMDE Manjaro
Noyau : 4.9 à 4.19
(G)UI : Xfce Mate
Inscription : 02-04-2011

Re : Un script shell de rangement...

Bonjour,
un rangement automatique et intelligent... je n'y crois pas big_smile.
Kao a raison, le risques d'écraser des fichiers est énorme.
Par contre j'ai la solution pour les photos : le renommage selon les infos Exif.
J'utilise jhead (https://la-vache-libre.org/jhead-un-out … -wave-etc/) pour nommer automatiquement toutes mes photos au format année_mois-jour_heure_minute_seconde. Mais je ne les laisse pas dans un seul et même répertoire car ça peinerait à s'ouvrir (ralentissement du à l'aperçu des vignettes).

Hors ligne

#4 04-12-2018 12:48:37

captnfab
Admin-Girafe
Lieu : /dev/random
Distrib. : Debian Stretch/Buster/Sid/Rc-Buggy
Noyau : Linux (≥ 4.12)
(G)UI : i3-wm (≥ 4.13)
Inscription : 07-07-2008
Site Web

Re : Un script shell de rangement...

Un petit script qui pourrait servir d'esquisse à ce que tu voulais faire au départ sans écraser les faux doublons (à améliorer pour prendre en compte le type mime) :
À essayer avec "echo" au lieu de "mv" d'abord…


SOURCE="mon/dossier/à/trier"
DEST="mon/dossier/destination"
find "$SOURCE" -type f -print0 | while IFS= read -r -d $'\0' f
do
  hash=$(md5sum "$f"|cut -f1 -d' ');
  bn=$(basename "$f");
  mv "$f" "${DEST}/${hash}_${bn}"
done


captnfab,
Association Debian-Facile, bépo.
TheDoctor: Your wish is my command… But be careful what you wish for.

Hors ligne

#5 04-12-2018 13:14:25

otyugh
CA Debian-Facile
Lieu : Quimperlé/Arzano
Distrib. : Debian Stable
Inscription : 20-09-2016
Site Web

Re : Un script shell de rangement...

Si on fait qu'à partir des extensions ça donne ça :

SRC='~/Bureau'
DST='/tmp'
find "$SRC" -name *.* -type f -print0 | while read -d '' file
do
    ext=${file##*.}
    echo mkdir -p "$DST/$ext"
    echo mv -i "$file" "$DST/$(basename $file)"
done



On pourrait l'améliorer pour les cas de doublons, genre si filename identique, vérifier shasum : si identique écraser, sinon changer le nom et... (boucle) jusqu'à ce qu'y ait plus de filename identique en destination.

Dernière modification par otyugh (04-12-2018 14:59:24)


Agenda du libre : venez aider et vous faire aider !
Arzano Informatique : mon entreprise gagne-pain.
Ma contribution au datalove

Hors ligne

#6 04-12-2018 14:48:10

captnfab
Admin-Girafe
Lieu : /dev/random
Distrib. : Debian Stretch/Buster/Sid/Rc-Buggy
Noyau : Linux (≥ 4.12)
(G)UI : i3-wm (≥ 4.13)
Inscription : 07-07-2008
Site Web

Re : Un script shell de rangement...

@otyugh: tu peux faire « si doublon -> je rajoute le hash dans le nom » ça évite de calculer le hash *tout le temps* comme je l'ai fait smile Et ça réduit fortement le risque d'écrasement (sauf collision md5, ce qui n'arrive que rarement par accident…)

captnfab,
Association Debian-Facile, bépo.
TheDoctor: Your wish is my command… But be careful what you wish for.

Hors ligne

#7 04-12-2018 15:04:31

otyugh
CA Debian-Facile
Lieu : Quimperlé/Arzano
Distrib. : Debian Stable
Inscription : 20-09-2016
Site Web

Re : Un script shell de rangement...

Ou alors faudrait faire un tableau "filename<>checksum" quand y a des doublons.
Le souci de les intégrer au fichier je pense, c'est que... Ça change le nom du fichier. big_smile (je sais, je suis un champion)

Agenda du libre : venez aider et vous faire aider !
Arzano Informatique : mon entreprise gagne-pain.
Ma contribution au datalove

Hors ligne

#8 04-12-2018 16:37:03

MicP
Membre
Inscription : 29-02-2016

Re : Un script shell de rangement...

Bonjour

On peut faire renommer les doublons par la commande mv
en utilisant l'option backup de cette commande
et la variable d'environnement VERSION_CONTROL :

ls -l rep1/ rep2/ rep3/ ciblerep/


ciblerep/:
total 0

rep1/:
total 12
-rw-r--r-- 1 michel michel 13 déc.   5 01:03 fich_1.txt
-rw-r--r-- 1 michel michel 18 déc.   5 01:03 fich_2.txt
-rw-r--r-- 1 michel michel 23 déc.   5 01:03 fich_3.txt

rep2/:
total 12
-rw-r--r-- 1 michel michel  4 déc.   5 01:03 fich_1.txt
-rw-r--r-- 1 michel michel  7 déc.   5 01:03 fich_2.txt
-rw-r--r-- 1 michel michel 10 déc.   5 01:04 fich_3.txt

rep3/:
total 12
-rw-r--r-- 1 michel michel 41 déc.   5 01:04 fich_1.txt
-rw-r--r-- 1 michel michel 74 déc.   5 01:04 fich_2.txt
-rw-r--r-- 1 michel michel 89 déc.   5 01:04 fich_3.txt


env VERSION_CONTROL=numbered mv --backup=t rep1/*.* rep2/*.* rep3/*.* ciblerep/
ls -l rep1/ rep2/ rep3/ ciblerep/


ciblerep/:
total 36
-rw-r--r-- 1 michel michel 41 déc.   5 01:04 fich_1.txt
-rw-r--r-- 1 michel michel 13 déc.   5 01:03 fich_1.txt.~1~
-rw-r--r-- 1 michel michel  4 déc.   5 01:03 fich_1.txt.~2~
-rw-r--r-- 1 michel michel 74 déc.   5 01:04 fich_2.txt
-rw-r--r-- 1 michel michel 18 déc.   5 01:03 fich_2.txt.~1~
-rw-r--r-- 1 michel michel  7 déc.   5 01:03 fich_2.txt.~2~
-rw-r--r-- 1 michel michel 89 déc.   5 01:04 fich_3.txt
-rw-r--r-- 1 michel michel 23 déc.   5 01:03 fich_3.txt.~1~
-rw-r--r-- 1 michel michel 10 déc.   5 01:04 fich_3.txt.~2~

rep1/:
total 0

rep2/:
total 0

rep3/:
total 0

Dernière modification par MicP (05-12-2018 02:07:32)

Hors ligne

#9 04-12-2018 17:09:29

empanada
Membre
Distrib. : Debian 9 (Stretch)
Noyau : 4.9.0-7-amd64
(G)UI : LXDE
Inscription : 19-09-2018

Re : Un script shell de rangement...

Des bonnes idées déjà. Je suis d'accord avec tout dit jusqu'au moment. Un mélange entre des idées déjà dites et quelques neuves:
- Difficile (mais pas imposible)
- Mieux peut-être d'utiliser les infos qui donne "file --mime-type" plutôt que les extensions. C'est plus complet et plus confiable.
- Dans certains fichiers il y a des infos extra fournis par les données EXIF et les données ID3 tag, par exemple, dans les fichiers audio. Pour les documents(doc, docx, odt, txt, pdf,....) , tu peut chercher des mots clés dans leur contenu, par exemple "facture", "travail",...
- Plus les infos obtenues, mieux sera le triage :  infos peuvent venir du nom de fichier, nom de répertoire, de l'extension, du mime-type, EXIF, ID3 , contenu, de la date de création et/ou modification...
- Peut-être le premier c'est s'en sortir d'entre les arbres pour mieux voir la forêt: faire un script pour récolter tous les infos, et les mètre sur une feuille de calcul, ou tu peux mieux planifier la procédure finale. Par exemple : une première colonne avec le chemin (sans le nom), une deuxième avec le nom, une troisième avec le mime-type, une quatrième avec la date de création, une autre colonne avec la date de modification, info EXIF si c'est une image, info ID3 tag si c'est un fichier audio, etc Après, avec cette info facile à voir et trier, mieux classer.

Il y a des rénommeurs en masse dans les dépôts debian, très puissantes () comme:
- Thunar Bulk Rename
- pyRenamer (entre autres, peux renommer en fonction des donnés EXIF et/ou ID3)
Il faut jouer un peu avec eux pour mieux en profiter, mais dans quelques minutes, on voit la puissance et ils sont faciles à utiliser.

Salut

Dernière modification par empanada (04-12-2018 17:11:29)


"blues are the roots and the other musics are the fruits" . Willie Dixon

En ligne

#10 04-12-2018 17:53:34

MicP
Membre
Inscription : 29-02-2016

Re : Un script shell de rangement...

En utilisant le nom d'extension de chaque fichier à déplacer pour créer les répertoires qui vont recevoir les fichiers
et en utilisant le renommage des doublons par la commande mv :

#!/bin/bash

repSource="cheminDuRépertoireSource"
repCible="cheminDuRépertoireCible"

while read; do
    extension="${REPLY##*.}"
    [ -d "$repCible/$extension" ] || mkdir "$repCible/$extension"
    env VERSION_CONTROL=numbered mv --backup=t "$REPLY" "$repCible/$extension/"
done <<< $(find "$repSource" -type f)

Dernière modification par MicP (04-12-2018 18:03:09)

Hors ligne

#11 05-12-2018 00:42:56

andrea86
Membre
Inscription : 28-11-2018

Re : Un script shell de rangement...

Bonsoir à tous!
Je suis très surpris que mon sujet attire les foules,mais aussi très reconnaissant pour le soutient et l'aide que vous m'apportezmerci.gif
Le seul problème c'est que j'ai oublié de préciser que j'ai pas un super niveau en ligne de commandepeace_flag.gif
..... Je n'imaginais pas que ça allait devenir vite très velu... du coup je pense que je vais peut être me rendre car le projet n'est pas à ma portée... cela me chagrine un peu...:rolleyes:

sauf si on peut faire une tentative d'y aller par étapes.. et en écrivant sous #ce que chaque commande va faire?

La première, je tenais vraiment a tout regrouper dans un seul dossier...

Cette manière de faire est faisable, même pour un newb comme moi, je crois que je la garde et je vais la tester de ce pas! (pas sur "the archive" bien sûrzen.gif)

Bonjour

On peut faire renommer les doublons par la commande mv
en utilisant l'option backup de cette commande
et la variable d'environnement VERSION_CONTROL :



L'idée de captnfab m'a semblé bien aussi, mais je ne gère pas bien les boucles, alors je potasse un peu le sujet avant de tester!

...
disons que pour quelqu'un qui voulait se rendre.... je suis cho au taquet big_smile

un grand merci!
Je reviens vers vous dés que j'ai tester ces deux choses , je pense demain dans la journée!

Hors ligne

#12 05-12-2018 01:34:53

MicP
Membre
Inscription : 29-02-2016

Re : Un script shell de rangement...

Bonjour

Une petite explication concernant le fonctionnement du script listé dans mon message précédent.

La commande find va lister tous les fichiers contenus dans le répertoire et les sous-répertoires
du répertoire dont le nom est dans la variable repSource
et va envoyer chacun de ces noms de fichier dans la boucle while …; do … done

NOTE :Il faudrait penser à modifier la ligne de commande find
de façon à ce que seuls certains fichiers soient listés (par exemple, en précisant une liste de nom d'extension à rechercher)
Sinon, tous les fichiers du répertoire source (et de ses sous-répertoires) seront listés et donc déplacés,
ce qui n'est peut-être pas ce que veux l'utilisateur…

tant que (while) la commande find enverra un nom de fichier dans la boucle while …; do … done
la commande read va associer ce nom de fichier à la variable REPLY
et exécuter toutes les lignes de commandes qui sont entre do et done

Entre do et donne,
la première ligne de commande va créer une variable nommée extension
à laquelle sera assigné tout ce qui suit le dernier point dans la valeur de la variable REPLY
La variable extension va donc contenir le nom d'extension du nom du fichier qui a été assigné à la variable REPLY

La deuxième ligne de commande effectue d'abord un test :
[ -d "$repCible/$extension" ]
qui permet de savoir si le nom de répertoire dans lequel le fichier devra être copié existe déjà.
Et si ce test retourne un résultat faux, la suite de la ligne de commande sera exécutée :
mkdir "$repCible/$extension"
ce qui fait que la commande mkdir va donc créer le répertoire de destination
seulement si ce répertoire n'existe pas encore.

La troisième ligne de commande va d'abord utiliser la commande env
env VERSION_CONTROL=numbered
pour créer la variable d'environnement VERSION_CONTROL
et y assigner la valeur numbered
et ensuite, la commande mv va déplacer le fichier dont le nom est dans la variable REPLY
dans le répertoire dont le nom est composé avec les variables repCible et extension

L'option backup=t avec la variable d'environnement VERSION_CONTROL dont la valeur assignée est numbered
permet à la commande mv de renommer le fichier déplacé au cas où ce nom de fichier existerait déjà dans le répertoire ciblé :

- Si le nom du fichier à déplacer est dudule.txt mais que ce nom de fichier existe déjà dans le répertoire cible,
le fichier à déplacer nommé dudule.txt, une fois déplacé sera renommé dudule.txt.~1~

- Si le nom du fichier à déplacer est dudule.txt mais que ce nom de fichier existe déjà dans le répertoire cible,
et si le fichier dudule.txt.~1~ existe aussi dans le répertoire cible,
le fichier à déplacer nommé dudule.txt, une fois déplacé sera renommé dudule.txt.~2~

- etc.

=======
Il faudrait peut-être ajouter dans la boucle while
une ligne de commande pour remplir un fichier "log"

Dernière modification par MicP (05-12-2018 09:54:10)

Hors ligne

#13 06-12-2018 10:31:17

captnfab
Admin-Girafe
Lieu : /dev/random
Distrib. : Debian Stretch/Buster/Sid/Rc-Buggy
Noyau : Linux (≥ 4.12)
(G)UI : i3-wm (≥ 4.13)
Inscription : 07-07-2008
Site Web

Re : Un script shell de rangement...

Une petite explication de ce script smile

# On définit les variables SRC (qui pointe vers le dossier contenant tous les fichiers/dossier/etc. à trier)
SRC="mon/dossier/à/trier"
# et DST (qui pointe vers le dossier où déplacer tout le bazar, qui ne doit pas être un sous-dossier de SRC.
DST="mon/dossier/destination"
# find renvoie la liste des fichiers (-type f) qui sont dans SRC ou un de ses sous-dossiers et affiche leur chemin complet en terminant par un \0
# while récupère chacun des noms (via read) en s'arrêtant de lire quand il voit un \0, et enregistre le chemin dans la variable f
find "$SRC" -type f -print0 | while IFS= read -r -d $'\0' f
do
  # basename récupère le nom du fichier ($f contient le chemin complet du fichier)
  bn=$(basename "$f");
  # md5sum calcul un hash, qui est une sorte d'identifiant (à peu près) unique du fichier
  # Comme md5sum renvoie aussi le nom de fichier, cut découpe la sortie pour ne récupérer que la première colonne (-f1), ces colonnes étant délimitées par des espaces (-d' ')
  hash=$(md5sum "$f"|cut -f1 -d' ');
  # mv déplace le fichier vers le répertoire destination avec le nom composé du hash et du nom d'origine
  mv "$f" "${DST}/${hash}_${bn}"
done



Une version qui ne calcule le hash que si un homonyme est rencontré, et qui ne crée pas de doublon :

SRC="mon/dossier/à/trier"
DST="mon/dossier/destination"
find "$SRC" -type f -print0 | while IFS= read -r -d $'\0' f
do
  bn=$(basename "$f");
  # Si un fichier homonyme existe déjà dans $DST
  if [ -e "${DST}/${bn}" ]
  then
    hash=$(md5sum "$f"|cut -f1 -d' ')
    hash_homonyme=$(md5sum "${DST}/${bn}"|cut -f1 -d' ')
    # Si nos fichiers sont différents
    if [ "$hash" != "$hash_homonyme" ]
    then
      # On déplace le fichier vers le répertoire destination avec le nom composé du hash et du nom d'origine
      mv "$f" "${DST}/${hash}_${bn}"
    else # Sinon, on supprime le doublon
      rm "${DST}/${hash}_${bn}"
    fi
  else # Sinon (si pas de fichier homonyme)
    # On déplace le fichier sans le renommer
    mv "$f" "${DST}/${bn}"
  fi
done




Je rappelle qu'avant de tester ces scripts en conditions réelles, il faut remplacer les occurrences de mv et de rm par echo mv et echo rm pour ne pas vraiment faire les opérations (un simple petit bug dans le script pourrait tout supprimer)


captnfab,
Association Debian-Facile, bépo.
TheDoctor: Your wish is my command… But be careful what you wish for.

Hors ligne

#14 07-12-2018 15:51:10

MicP
Membre
Inscription : 29-02-2016

Re : Un script shell de rangement...

#!/bin/bash

repSource="/chemin/du/répertoire/source"
repCible="/chemin/du/répertoire/cible"
lstExt="(wav|mp3|ogg|avi|mp4|jpg|jpeg|gif)"       # Liste des noms d'extension des fichiers à prendre en compte (à compléter si besoin)
lstRepsAexclure="($repSource)"                    # Liste des répertoires qui ne seront PAS pris en compte dans la recherche (chaque chemin de répertoire de la liste est à séparer par un caractère | )

fichLogs="$HOME/.log/deplacements.log"
[ -d "$HOME/.log/" ] || mkdir "$HOME/.log"        # S'il n'existe pas encore, créer le répertoire pour le fichier logs

repTmp="$(mktemp -d /tmp/pourTestsDoublons.XXX)"  # Pour comparer les nomDeFichier+MD5SUM

shopt -s nullglob                                 # Pour que le tableau lstFichs puisse être à 0 éléments
export VERSION_CONTROL=numbered                   # Pour que la commande mv ajoute un numéro au nom du fichier si ce nom de fichier existe déjà dans le répertoire cible
while read; do
    extension="${REPLY##*.}"                                                            # Récupérer le nom d'extension du fichier
    [ -d "$repCible/$extension" ] || mkdir "$repCible/$extension"                       # S'il n'existe pas encore, créer le répertoire cible avec le nom d'extension
    nomFichier="${REPLY##*/}"                                                           # Récupérer le nom du fichier sans son chemin
    if [ -f "$repCible/$extension/$nomFichier" ]; then {                                # Si nomFichSource existe déjà dans cible
        lstFichs=($repTmp/$nomFichier*)                                                   # Créer un tableau liste des fichiers du même nom dont la somme MD5 a déjà été calculée
        if [ ${#lstFichs[@]} -eq 0 ]; then {                                              # Si aucun nom de fichier de la liste ne commence par ce nom du fichier => la somme MD5 de ce fichier n'a PAS encore été calculée
            somMD5cible="$(md5sum $nomFichier | cut -d ' ' -f1)"                            # Calculer la somme md5 du fichier existant dans le répertoire ciblé
            touch "$repTmp/$nomFichier.$somMD5cible"                                        # Créer un fichier vide dans le répertoire temporaire en ajoutant à son nom la somme md5 du fichier cible
        }
        fi
        somMD5src="$(md5sum $nomFichier | cut -d ' ' -f1)"                                # Calculer la somme md5 du fichier source
        if [ -f "$repTmp/$nomFichier.$somMD5src" ]; then {                                # Si nomFichSource+SommeMD5source n'existe PAS dans le repertoire temporaire
            touch "$repTmp/$nomFichier.$somMD5src"                                          # Créer dans repTemporaire un fichier vide nommé nom du fichier + valeur MD5SUM source
            mv --backup=t "$REPLY" "$repCible/$extension/"                                  # Déplacer le fichier source dans le répertoire ciblé (en ajoutant à son nom, si besoin, une numérotation)
            echo "\"$REPLY\" a été déplacé dans \"$repCible/$extension/\"" >>  "$fichLogs"  # Enregistrer dans le fichier logs le nom du répertoire cible et le chemnin+nom du fichier source qui a été déplacé
        }
        else {              
            rm ${REPLY}                                       # Même nom de fichier + même MD5 => c'est un doublon => supprimer le fichier doublon dont l'original a déjà été déplacé
            echo "\"$REPLY\" a été suprimé." >> "$fichLogs"   # Enregistrer dans le fichier logs le nom du fichier source qui a été suprimé
        }
        fi
    }
    else {                                                                              # Le fichier source n'existe pas dans la cible
        mv --backup=t "$REPLY" "$repCible/$extension/"                                    # Déplacer le fichier source dans le répertoire ciblé (en ajoutant à son nom, si besoin, une numérotation)
        echo "\"$REPLY\" a été déplacé dans \"$repCible/$extension/\"" >>  "$fichLogs"    # Enregistrer dans le fichier logs le nom du répertoire cible et le chemnin+nom du fichier source qui a été déplacé
    }
    fi
done <<< $(find "$repSource" -type d -regex "$lstRepExclus" -prune -o -regextype posix-extended -iregex "$repSource*\.$lstExt" -a -type f -print)

rm -Rf repTmp      # Supprimer le répertoire temporaire

Dernière modification par MicP (07-12-2018 18:23:38)

Hors ligne

Pied de page des forums