Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 23/04/2011, à 14:57

Sarya

Comment effectuer une tache sur le premier fichier d'un dossier ?

Bonjour !
Je réalise un petit script de tri de fichier en fonction de leur type, qui déplace les fichiers dans les dossiers correspondants, créés au préalable.

Je pensais faire une boucle while du genre "temps que le nombre de fichier présents n'est pas 0, fait ça :"
et puis après coller un if pour le triage proprement dit.

Le problème c'est que qu'en entrée de ma boucle if il me faudrait un fichier, le premier de mon dossier, mais je sais pas du tout comment l'appeler. Pour le moment voilà ce que j'ai :

n=ls -1 | wc -l   #comptage du nombre de fichiers dans le dossier courant

while [ "$n" != "0" ]  
    do   
file "fichier"
read ext

if [ "ext" = "music" ]; then
{
      mv "fichier" Music
}
elif .... #etc avec les autres types de fichiers (Vidéos,Images,Autres...)....

fi
od

exit 0

Voilà, mon problème est donc d'appeler "fichier" dans l'instruction file. Je me fout de savoir lequel il prend, je veux qu'il en prenne un et qu'il le déplace comme il faut... Des idées ?
Par ailleurs, par rapport à l'instruction file, qui est celle que j'ai trouvé pour détecter le type de fichier, la sortie est assez longue et je ne suis pas sûr que ce soit la meilleure façon de sélectionner les fichier d'après leur types, surtout pour comparer ça a autre chose dans le "if"... (je suis pas sûr de bien me faire comprendre roll

Anyway, si quelqu'un entend cet appel au secours et y répond, je lui en serait éternellement reconnaissant big_smile

Hors ligne

#2 Le 23/04/2011, à 15:30

aduxas

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

As-tu considéré

for file in *; do ...; done

Hors ligne

#3 Le 23/04/2011, à 17:21

FRUiT

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Et ce n'est pas

while cond; do
od

mais

while cond; do
done

D'autre part au lieu d'enchainer des elifs, tu devrais utiliser "case".


Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean

Hors ligne

#4 Le 24/04/2011, à 21:55

Levi59

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Essaye ceci (Code à compléter):

## DOSSIERS
IMAGES="/chemin/vers/dossier/images"
VIDEOS="/chemin/vers/dossier/videos"
AUDIO="/chemin/vers/dossier/audio"
etc

while read
do
    EXT="${REPLY##*.}"
    case "${EXT}" in
    avi|mpeg) DEST="${VIDEOS}";;
    jpg|png) DEST="${IMAGES}";;
    mp3|ogg)  DEST="${AUDIO}";;
    etc
    *) echo "Format inconnu" ; exit ;;
    esac

    mv "${REPLY}" "${DEST}"

done < <(ls)

Hors ligne

#5 Le 29/04/2011, à 13:44

Sarya

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Super ! Avec tout ça je devrais arriver à faire un truc qui fonctionne !!
Merci à tous !

Hors ligne

#6 Le 01/05/2011, à 22:28

sputnick

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

award?v=ls&n=Levi59
http://partmaps.org/era/unix/award.html

big_smile

De plus, sous Linux ya plus évolué que se baser sur l'extension des fichiers. Si tu enregistre un tag.gz en .zip, est-ce que ton script va bien le gérer ?

Tu te limite au dossier courant. Ma version gere n'importe quel (suite d') argument(s), ex :

./script ~/*.jpg ~/*.pdf /path/elsewhere/*

Solution largement commentée :

#!/bin/bash
# made by sputnick 20110501
# Version du script de Levi59 amélioré -> http://forum.kubuntu-fr.org/viewtopic.php?id=456701

## DOSSIERS
IMAGES="/chemin/vers/dossier/images"
VIDEOS="/chemin/vers/dossier/videos"
AUDIO="/chemin/vers/dossier/audio"
# AUTRES A COMPLETER...

# pas besoin de faire "for F in; do",
# bash va lire directement les fichiers
# donnés en paramètre.
for F; do
    go=true
    # on utilise directement la sortie de la commande file
    # pour chercher son vrai type
    # indépendamment de l'extension.
    # Voir "man 1 file"
    case $(file "$F") in
        *Video*) DEST="${VIDEOS}";;
        *image*) DEST="${IMAGES}";;
        *Audio*) DEST="${AUDIO}";;
        # a completer, faire "file <FICHIER>" pour voir son type...
        *) go=false; echo >&2 "Format inconnu pour ${F}" ;;
    esac

    # -i demande confirmation avant d'écraser un fichier
   [[ $go = true ]] && mv -i "${F}" "${DEST}"
done

Dernière modification par sputnick (Le 01/05/2011, à 22:35)


On ne peut pas mettre d'array dans un string!
https://sputnick.fr/

Hors ligne

#7 Le 01/05/2011, à 23:08

sputnick

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

La dernière solution que j'ai donnée est pour tous les fichiers en arguments avec le système des globs.

Cette nouvelle version est conforme à la spec, à savoir gérer uniquement le premier fichier des répertoires donnés en argument.

#!/bin/bash
# made by sputnick 20110502
# Version du script de Levi59 amméllioré -> http://forum.kubuntu-fr.org/viewtopic.php?id=456701

## DOSSIERS
IMAGES="/chemin/vers/dossier/images"
VIDEOS="/chemin/vers/dossier/videos"
AUDIO="/chemin/vers/dossier/audio"
# AUTRES A COMPLETER...

# pas besoin de faire "for REP in; do",
# bash va lire directement les répertoires
# donnés en paramètre.
for REP; do
    c=0
    go=true
    if [[ ! -d "${REP}" ]]; then echo >&2 "${REP} n'est pas un repertoire tudjuuu ! On quitte..."; exit 1; fi

    # on utilise un array (tableau, matrice) pour pouvoir 
    # traiter le premier fichier du répertoire
    ARR=( ${REP}/* )

    # tant que l'on ne trouve pas un fichier (au lieu d'un sous répertoire),
    # on boucle et on itère le compteur $c
    while [[ ! -f "${ARR[c]}" && -e "${ARR[c]}" ]]; do ((c++)); done

    # si le while a trouvé un fichier ok,
    # sinon on switch de répertoire
    [[ -f "${ARR[c]}" ]] || continue

    # on utilise directement la sortie de la commande file
    # pour chercher son vrai type
    # indépendamment de l'extension.
    # Voir "man 1 file"
    case $(file "${ARR[c]}") in
        *Video*) DEST="${VIDEOS}";;
        *image*) DEST="${IMAGES}";;
        *Audio*) DEST="${AUDIO}";;
        # a completer, faire "file <FICHIER>" pour voir son type...
        *) go=false; echo >&2 "Format inconnu pour ${ARR[c]}" ;;
    esac

    # -i demande confirmation avant d'écraser un fichier
   [[ $go = true ]] && mv -i "${ARR[c]}" "${DEST}"
done

Dernière modification par sputnick (Le 01/05/2011, à 23:17)


On ne peut pas mettre d'array dans un string!
https://sputnick.fr/

Hors ligne

#8 Le 07/05/2011, à 10:39

Levi59

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Retour après 10 jours d'absence

@sputnick
Ok ls n'était pas nécessaire mais mon code n'était pas vraiment fonctionnel, c'était juste un exemple à modifier. L'extension, c'est pas non plus la meilleur solution mais c'était la plus simple pour l'exemple, j'avais d'ailleurs déjà écrit un script de tri qui utilisait les types mimes donc ce n'était pas la peine de me sortir le golden award. Mon but était juste d'orienter Sarya sur une solution possible...

Hors ligne

#9 Le 07/05/2011, à 15:57

sputnick

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Levi59 a écrit :

...ce n'était pas la peine de me sortir le golden award. Mon but était juste d'orienter Sarya sur une solution possible...

C'est de l'humour tu sais ? smile

C'est juste une extension de la culture Unix autour du célèbre http://partmaps.org/era/unix/award.html

On a tous à un moment T eu droit à des awards, moi y compris ^^


On ne peut pas mettre d'array dans un string!
https://sputnick.fr/

Hors ligne

#10 Le 07/05/2011, à 17:40

Levi59

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Je n'étais ni énervé ni vexé, c'était juste pour préciser puisque dans ce cas je ne cherchais pas la perfection mais juste à être didactique.

Hors ligne

#11 Le 07/05/2011, à 18:03

01franz

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

bonsoir

merci le script peu tout-jour servir.


toujours utile
sudo tail -f /var/log/syslog

Hors ligne

#12 Le 07/05/2011, à 18:51

sputnick

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Levi59 a écrit :

Je n'étais ni énervé ni vexé, c'était juste pour préciser puisque dans ce cas je ne cherchais pas la perfection mais juste à être didactique.

Cool, tant que ya pas des horreurs comme des

for i in `ls`

qui BREAK les fichiers avec espaces, moi je dit rien wink


On ne peut pas mettre d'array dans un string!
https://sputnick.fr/

Hors ligne

#13 Le 07/05/2011, à 18:57

01franz

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

pour les espace une piste

for f in *; do
    echo $f
     file=$(echo $f | tr A-Z a-z | tr ' ' _ |tr '( ) , : / \ ; [ ] |   » « ' _)
     [ ! -f $file ] && mv "$f" $file
ls
done

toujours utile
sudo tail -f /var/log/syslog

Hors ligne

#14 Le 07/05/2011, à 19:06

sputnick

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

NOPE, the reply must be "USE MORE QUOTES!"


On ne peut pas mettre d'array dans un string!
https://sputnick.fr/

Hors ligne

#15 Le 08/05/2011, à 13:55

FRUiT

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

J'avais une petite interrogation au sujet du for in ls.

Actuellement je bosse  sur un menu déroulant non graphique en sh pour serveur, basé sur ncurses. Ca lance des commandes, ce sera donc à mi chemin entre des alias organisés et des listes de bookmarks.

Les menus (à remplir par l'utilisateur) sont des chemins de type :

/home/session/.qmenu/profileexemple_1_Q.qmenu
/home/session/.qmenu/profileexemple_2_Sytem.qmenu
...
/home/session/.qmenu/profileexemple_10_Power.qmenu

Soit en gros :

${PATH}/${PROFILE}_${ID}_${NAME}.qmenu

Les menus sont donc indexés. Lors du démarrage du programme, le profile en question est scanné et ré-indexé (par exemple si un menu a été supprimé manuellement dans le dossier .qmenu, l'index devient incohérent, il faut alors le réorganiser).

J'ai donc quelquechose du style :

    ...
    ID=1

    for M in $(\ls -1 -v "${HOME}"/.qmenu/${PROFILE}_*.qmenu 2>/dev/null); do

        [ -f "$M" ] || continue

        hash_menu "$M"
        M_TARGET="${FOUND_PATH}/${FOUND_PROFILE}_${ID}_${FOUND_NAME}.${FOUND_EXT}"

        status "Indexing : $(printf "%2s" "$ID") [ profile « $PROFILE » , menu « $FOUND_NAME » ]"

        [ "$M_TARGET" = "$M" ] || mv "$M" "$M_TARGET"

        etc......

        ID=$(($ID+1))

    done

Le "ls -v" conserve l'ordre naturel des nombres (de l'index, donc) ce qui me permet de réorganiser l'index en une suite cohérente d'entiers tout en conservant l'ordre original des menus.

Bien évidemment, cela ne gère donc pas les espaces, c'est pourquoi intervient la ligne :

        [ -f "$M" ] || continue

Ce n'est pas très grave car les noms des menus ne sont pas sensés contenir des espaces (et j'en interdis la possibilité lors de la création d'un nouveau menu). Il n'en reste pas moins que c'est un méchant for in ls tout à fait inélégant... Et aussi j'aurais bien voulu que les profiles, eux, puissent contenir des espaces par exemple.

Donc, dans un cas comme celui-ci, quelle serait la solution pour se passer de ls (ou de for, ou de while ce qui revient au même) ? En sh bien sùr ?

Dernière modification par FRUiT (Le 08/05/2011, à 14:33)


Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean

Hors ligne

#16 Le 08/05/2011, à 14:00

FRUiT

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Et autre question, un nom de session linux peut-il ou non contenir un espace ?

Genre "/home/albert dupont/"


Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean

Hors ligne

#17 Le 08/05/2011, à 14:37

sputnick

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

GASP ! Si tu relis le fil, j'explique que

for i in $(ls)

c'est la loose assurée.

Tu a besoin des globs pour ne pas créer le fameux "useless use of ls"

C'est archi simple :

for i in "${HOME}"/.qmenu/${PROFILE}_*.qmenu; do ...

On ne peut pas mettre d'array dans un string!
https://sputnick.fr/

Hors ligne

#18 Le 08/05/2011, à 14:41

FRUiT

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Oui mais si tu relis bien mon message, en  reprenant ton exemple, le menu 10 va passer avant le menu 2 ............


Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean

Hors ligne

#19 Le 08/05/2011, à 14:58

sputnick

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Je te conseille une autre convention de nommage (renommer en masse tes fichiers avec prename) du style :

00001
00002
...

On ne peut pas mettre d'array dans un string!
https://sputnick.fr/

Hors ligne

#20 Le 08/05/2011, à 15:45

FRUiT

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Mmm le problème c'est que ça m'obligerait a faire des printf "%02d" et/ou des découpages de variables partout dans le script... J'avais déjà envisagé cette possibilité je vais lui redonner une chance...

Dernière modification par FRUiT (Le 08/05/2011, à 15:49)


Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean

Hors ligne

#21 Le 08/05/2011, à 16:21

sputnick

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Sinon au pire ya aussi cette solution :

for i in "${HOME}"/.qmenu/${PROFILE}_*[0-9] .qmenu  "${HOME}"/.qmenu/${PROFILE}_*[0-9][0-9] .qmenu

On ne peut pas mettre d'array dans un string!
https://sputnick.fr/

Hors ligne

#22 Le 08/05/2011, à 17:01

FRUiT

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Plutôt comme ça :

for i in "${HOME}"/.qmenu/${PROFILE}_[0-9]_*.qmenu  "${HOME}"/.qmenu/${PROFILE}_[0-9][0-9]_*.qmenu

Ca semble bien marcher après 2 ou 3 tests... Merci j'y avais pas pensé smile


Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean

Hors ligne

#23 Le 08/05/2011, à 17:17

sputnick

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

Wé mais la solution de renommage reste quand même plus propre...


On ne peut pas mettre d'array dans un string!
https://sputnick.fr/

Hors ligne

#24 Le 08/05/2011, à 17:54

FRUiT

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

J'utilise beaucoup seq... Si y'a un moyen de lui faire énumérer 01 02 03 04 05, là je dis pas mais sinon, le coup des [1-9] et [1-9][0-9] me parait le plus rapide et utilisant moins d'outils. La rapidité étant un facteur déterminant dans ce script en particulier.

Je me limite (à part mv, cp et rm) à : tput, stty, seq, awk, ls.

Dernière modification par FRUiT (Le 08/05/2011, à 18:01)


Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean

Hors ligne

#25 Le 08/05/2011, à 18:59

aduxas

Re : Comment effectuer une tache sur le premier fichier d'un dossier ?

seq -f "%02.0f" 1 5
01
02
03
04
05

Hors ligne