#1 Le 20/02/2020, à 16:42
- Fantakov
[Résolu] Boucle for traitée par taille
Bonjour à tous,
J'ai un dossier contenant plusieurs dizaines de milliers d'images de tout types et tailles que j'aimerais diviser en plusieurs dossiers de 1000 images.
J'ai trouvé un bout de code sur le forum que j'ai un peu modifié et qui fonctionne très bien pour répartir les fichiers dans des dossiers de 1000 :
nbImg=1000
cpt=0
j=0
mkdir img$j
for i in * ; do
cpt=`expr $cpt + 1`
mv "$i" $PWD/img$j
modulo=`expr $cpt % $nbImg`
if [ $modulo -eq 0 ]; then
j=`expr $cpt / $nbImg`
mkdir img$j
fi
done
Le problème c'est que j'aimerais qu'ils soient triés par taille avant d’être dispatchés.
En gros avoir les images de plusieurs Mo dans le dossier img1 et celles de 2ko dans le dossier img50.
Comment demander à for de faire son boulot par ordre de taille ?
Merci
Dernière modification par Fantakov (Le 20/02/2020, à 18:47)
Hors ligne
#2 Le 20/02/2020, à 17:28
- pingouinux
Re : [Résolu] Boucle for traitée par taille
Bonjour,
Tu peux essayer ceci (c'est du bash)
nbImg=1000
rep=0
n=0
mkdir "img$rep"
while read fic; do
if ((n==nbImg)); then
n=0
((rep++))
mkdir "img$rep"
fi
mv "$fic" "$PWD/img$rep"
((n++))
done < <(ls -S *)
Hors ligne
#3 Le 20/02/2020, à 18:38
- Watael
Re : [Résolu] Boucle for traitée par taille
je ne le dirai jamais assez : gare aux fichiers avec des espaces dans leur nom !
$ while read -d '' size filename; do echo ">$filename<"; done < <(find ./ -maxdepth 1 -type f -printf '%s %p\0' | sort -z -k1,1n )
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#4 Le 20/02/2020, à 18:41
- Fantakov
Re : [Résolu] Boucle for traitée par taille
Salut, ça marche comme il faut c'est impeccable les fichiers se rangent correctement dans leurs dossiers par taille.
Seul petit détail, à la fin du script pour chaque fichier ça m'affiche une ligne du type
mv: impossible d'évaluer 'monfichier': Aucun fichier ou dossier de ce type
Je risque de réutiliser de temps en temps se script si jamais tu sais comment cacher l'erreur (pour le coté esthétique).
En tout cas les fichiers sont correctement déplacés c'est le principal.
Merci beaucoup Pingouinux !
edit pour Watael : J'ai vérifié pour le script de Pingouinux et celui que j'ai mis en post 1 les deux traitent bien les fichiers avec des espaces, les variables sont entre guillemets.
Dernière modification par Fantakov (Le 20/02/2020, à 18:46)
Hors ligne
#5 Le 20/02/2020, à 19:14
- Watael
Re : [Résolu] Boucle for traitée par taille
je compte les retours chariot dans les espaces.
j'ai oublié de mettre des points de suspension : espaces,...
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#6 Le 20/02/2020, à 19:30
- kamaris
Re : [Résolu] Boucle for traitée par taille
Ouais, ben moi je dis que c'est pas assez tout ça, parce que si j'ai des antislashs dans mes noms de fichier, ou des espaces à la fin, ça marchera pas
Donc :
while IFS='' read -rd '' line; do echo ">${line#* }<"; done < <(find ./ -maxdepth 1 -type f -printf '%s %p\0' | sort -z -k1,1n )
Hors ligne
#7 Le 20/02/2020, à 19:44
- pingouinux
Re : [Résolu] Boucle for traitée par taille
Je risque de réutiliser de temps en temps se script si jamais tu sais comment cacher l'erreur (pour le coté esthétique).
Ceci devrait être mieux, mais c'est du bricolage
nbImg=1000
rep=0
n=0
mkdir "img$rep"
while read fic; do
[ -d "$fic" ] && continue
if ((n==nbImg)); then
n=0
((rep++))
mkdir "img$rep"
fi
mv "$fic" "$PWD/img$rep"
((n++))
done < <(ls -Sd *)
Hors ligne
#8 Le 20/02/2020, à 20:05
- Watael
Re : [Résolu] Boucle for traitée par taille
ça ne règle pas le "problème" des retours chariot.
et find ne retourne que les fichiers.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#9 Le 20/02/2020, à 20:22
- Fantakov
Re : [Résolu] Boucle for traitée par taille
Impeccable !
Même si c'est du bricolage ça me vas très bien pour le peu que j'en aurait besoin.
C'est surtout que si je ne l'utilise pas à nouveau avant quelques mois j'éviterais de me poser des questions en voyant les erreurs.
C'est pour trier des fichiers récupérés avec photorec donc ils sont tous nommés sans espaces ni caractères spéciaux du type "f134534354.jpg"
Encore merci à vous pour l'aide !
Hors ligne
#10 Le 20/02/2020, à 20:36
- Watael
Re : [Résolu] Boucle for traitée par taille
c'est "pédagogique".
quand de futurs lecteurs chercheront une méthode pour faire la même chose dans un contexte différent, il auront une méthode sûre.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#11 Le 20/02/2020, à 22:34
- kamaris
Re : [Résolu] Boucle for traitée par taille
Une autre manière de faire : laisser xargs faire les paquets de 1000 fichiers, et donc esquiver la boucle while de lecture du flux, mais au prix d'un mini-script.
J'ai inversé le sens du sort pour bien correspondre à la demande en #1, comme le fait le ls -S (malgré toutes ses imperfections).
find ./ -maxdepth 1 -type f -printf '%s %p\0' | sort -z -k1,1nr | xargs -0 -L1000 bash -c 'i=""; while test -d "img$i"; do ((i++)); done; mkdir "img$i"; mv -t "img$i" "${@#* }"' _
---
NB : sur certains systèmes, il peut y avoir une limitation au niveau du nombres de mots que peut contenir une ligne de commande.
Si la commande ci-dessus dépasse ce nombre, il faut passer moins d'arguments à la fois par xargs, et complexifier un peu le mini-script pour remplir correctement les répertoires (ou réaliser un post-traitement pour regrouper les contenus de répertoires).
Mais même dans ce cas, cette manière de faire doit être significativement plus performante qu'une boucle while (même si on y regroupait les appels à mv, au lieu d'en faire un par fichier à déplacer).
Dernière modification par kamaris (Le 20/02/2020, à 23:50)
Hors ligne