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 08/06/2008, à 23:38

Pandark

Gestion de la corbeille Nautilus par Bash

Bonjour, bonsoir ou bonne nuit big_smile,
J'ai rédigé un script (en fait, une partie de mon .bashrc) pour envoyer des fichiers dans la corbeille de Nautilus au lieu de les supprimer directement lorsque j'utilise la fonction rm.
J'ai essayer de faire une mimique du comportement de Nautilus (même numérotation des homonymes, fichiers d'infos identiques...) et de rester proche des options de rm (-ivfr).
À priori, ça marche, tant qu'il n'y a ni espaces ni guillemets (simples ou doubles) dans les chemins et noms des fichiers...

Donc en gros, il faudrait corriger ce bug, et après ajouter une fonction de listage des fichiers de la corbeille et une de restauration de fichiers depuis la corbeille (certains essaient de le rajouter dans Nautilus).

Si vous avez une idée de comment corriger le bug existant ou si trouvez d'autres bugs... smile

alias rm='rm_to_trash'
function rm_to_trash()
(
#Fonction d'envoi dans la corbeille de Nautilus, par Pandark
    opt=-T
    trash_folder=~/.local/share/Trash

    while getopts ":IiFfRrVv" OPTION
    do
        case $OPTION in
            F|f)  # option "-f"
                opt+="f"
                force="yes"
            ;;
            r|r)  # option "-r"
                opt+="r"
            ;;
            I|i)  # option "-i"
                interactive="yes"
            ;;
            V|v)  # option "-v"
                verbose="yes"
            ;;
            :)  # pas d'option
            ;;
            \?) # option incorrecte
                echo -e "Option invalide\n"
                echo "Usage : rm [option] [paramètre]"
                echo "Options = -i (interactif) ou -f (forcé) ou -r (récursif) ou -v (bavard)"
                echo "Suppression directe : \rm"
                exit
            ;;
        esac
    done

    shift $(($OPTIND - 1)) #On place le curseur après les options

    for filename in "$@"
    do
        if [ -e "$filename" ]
        then
            filepath=`dirname "$filename"`; filepath=`readlink -f "$filepath"`
            new_filename="$filepath/${filename##*/}"
            if [ "$interactive" = "yes" -a "$force" != "yes" ]
            then
                PS3="Déplacer le fichier \`$filename' dans la corbeille ?"   # le prompt/la question
                select choix in "[y]es" "[n]o"; do
                    case $REPLY in
                        1|Y*|y*)
                            confirmed="yes"
                        break
                        ;;
                        2|N*|n*)
                            confirmed="no"
                        break
                        ;;
                    esac
                done
            fi
            if [ "$confirmed" != "no" ]
            then
                if [ -e "$trash_folder/files/${new_filename##*/}" ] # Si un fichier du même nom existe dans la corbeille...
                then
                    copie=2
                    new_filename="$filepath/${filename%%.*}.$copie.${filename#*.}"
                    while [ -e "$trash_folder/files/${new_filename##*/}" ] # Tant qu'un fichier du même nom existe dans la corbeille...
                    do
                    let "copie += 1"
                    new_filename="$filepath/${filename%%.*}.$copie.${filename#*.}"
                    done
                fi
#TODO : gestion des espaces, guillemets simples et guillemets doubles
                mv $opt "$filename" "$trash_folder/files/${new_filename##*/}"
                echo -e "[Trash Info]\nPath=$filepath/${filename##*/}\nDeletionDate=`date +"%FT%T"`" > "$trash_folder/info/${new_filename##*/}.trashinfo"
                if [ "$verbose" = "yes" ]; then echo -e "Le fichier $filename est déplacé dans la corbeille."; fi
            fi
        else
            echo -e "$filename : Aucun fichier ou repertoire de ce type"
        fi
    done
)

Une autre fonction, juste pour vider la corbeille:

function empty_trash()
(
#Fonction pour vider la corbeille de Nautilus, par Pandark
    trash_folder=~/.local/share/Trash
    \rm $trash_folder/files/* $trash_folder/info/*
)

Dernière modification par Pandark (Le 09/06/2008, à 10:27)


Pandark
99% libre…

Hors ligne

#2 Le 09/06/2008, à 02:24

yurek

Re : Gestion de la corbeille Nautilus par Bash

si tu pouvais expliquer ton code: je décroche a partir du while


http://doc.ubuntu-fr.org/installation/debutants
http://doc.ubuntu-fr.org/diagnostic
http://doc.ubuntu-fr.org/diagnostic_outils
http://doc.ubuntu-fr.org/reflexe_ubunteros

Hors ligne

#3 Le 09/06/2008, à 05:24

Pandark

Re : Gestion de la corbeille Nautilus par Bash

Alors pour le getopts du début, un exemple bien expliqué sur HFR et
Des extraits du man

getopts chaîne_d_options nom [arguments]
Il place également l'index de l'argument suivant à analyser dans la variable OPTIND. OPTIND est initialisé à 1 à chaque lancement d'un shell ou d'un script.
[...]
Si le premier caractère de la chaîne_d_options est un deux-points, les erreurs sont renvoyées de manière silencieuse.
[...]
Si une option illégale est rencontrée, getopts met un point d'interrogation ? dans la variable nom, affiche un message d'erreur (s'il n'est pas en mode silencieux), et détruit la variable OPTARG. Si getopts fonctionne en mode silencieux, le caractère d'option est placé dans OPTARG et aucun message de diagnostique n'est affiché.

Don là ça devrait aller jusqu'au shift (le commentaire de cette ligne étant assez explicite)...

    for filename in $@
    do
        if [ -e "$filename" ]
        then

Pour tout fichier existant passé en argument

                PS3="Déplacer le fichier \`$filename' dans la corbeille ?"   # le prompt/la question
                select choix in "[y]es" "[n]o"; do
                    case $REPLY in
                        1|Y*|y*)
                            confirmed="yes"
                        break
                        ;;
                        2|N*|n*)
                            confirmed="no"
                        break
                        ;;
                    esac
                done

Là, ça me semble assez clair... il faut savoir que PS3 et $REPLY sont standards, donc ça va afficher les choix, puis la question et récupérer la réponse de l'utilisateur. Si ce n'est ni y... ni n..., ça va recommencer la boucle.

                    copie=2
                    new_filename="`dirname $filename`/${filename%%.*}.$copie.${filename#*.}"

Pour cette partie là, il faut savoir que Nautilus commence à numéroter à 2 le premier fichier pour lequel un fichier du même nom existe déjà dans la corbeille, et qu'il ajoute ce numéro après le premier point dans le nom du fichier (par exemple "mon.fichier.a.moi.txt" -> "mon.2.fichier.a.moi.txt" si c'est le deuxième fichier de ce nom supprimé)

Pour comprendre tous les ${filename%%.*}, ${filename#*.}, etc. ou `dirname $filename`, :

http://loquehumaine.wordpress.com/2007/11/12/script-bash3-renommer-plusieurs-fichiers-rename-a-bunch-of-files/ a écrit :

Avec ## (resp. #) on peut supprimer la plus longue (resp. courte) chaine correspondant au motif :

    $ Nom=’Rep/toto.tar.gz’
    $ echo ${Nom##*.}
    > gz
    $ echo ${Nom#*.}
    > tar.gz
    $ echo ${Nom##*t}
    > ar.gz
    $ echo ${Nom#*t}
    > oto.tar.gz

Pour faire la même chose avec la fin de la chaine, utilisez % (ou %%) :

    $ echo ${Nom%.*}
    > Rep/toto.tar
    $ echo ${Nom%%.*}
    > Rep/toto
    $ echo ${Nom%%t*}
    > Rep/
    $ echo ${Nom%t*}
    > Rep/toto.

Pis

Man a écrit :

dirname - strip non-directory suffix from file name


Pandark
99% libre…

Hors ligne

#4 Le 09/06/2008, à 06:08

Alain.g

Re : Gestion de la corbeille Nautilus par Bash

Bonjour

Il faut placer les variables entre guillemets, exemple :
→ for i in "$@"
→ mv "$bidule"

http://abs.traduc.org/abs-5.3-fr/ch05.html#quotingvar

Pas seulement pour les espaces, mais aussi pour les autres caractères spéciaux :
f=*
rm "$f" # effacera uniquement le fichier se nommant *
rm $f # effacera tous les fichiers (sauf cachés et dossiers) du répertoire

Dernière modification par Alain.g (Le 09/06/2008, à 06:09)


Xubuntu Karmic !

Hors ligne

#5 Le 09/06/2008, à 10:26

Pandark

Re : Gestion de la corbeille Nautilus par Bash

Ok, je crois que c'est mieux maintenant (je modifie dans le premier message)
Autre bug corrigé : le chemin inscrit dans le fichier info était relatif au lieu d'être absolu.


Pandark
99% libre…

Hors ligne

#6 Le 10/06/2008, à 01:16

Pandark

Re : Gestion de la corbeille Nautilus par Bash

Voilà une fonction pour lister le contenu de la corbeille (avec date de suppression et emplacement d'origine)
Mais ça m'embête d'utiliser IFS=$'\n', donc si quelqu'un a une autre méthode...
D'ailleurs, est-ce que je dois sauvegarder la valeur de IFS et la remettre à la fin dans le cas présent, ou est-ce que ça reviendra tout seul à la valeur d'origine ?

function ls_trash()
(
#Fonction pour lister le contenu dee la corbeille de Nautilus, par Pandark
    IFS=$'\n' # a cause des espaces du ls
    trash_folder=~/.local/share/Trash
    i=0
    echo "fichier | nom original | date de suppression"
    for residu in `ls "$trash_folder/files/"`
    do
        filename[$i]="$residu"
        if [ -e "$trash_folder/info/${filename[$i]}.trashinfo" ]
        then
            truename[$i]="`sed -n "s/Path=\(.*\)/\1/p" "$trash_folder/info/${filename[$i]}.trashinfo"`"
            deldate[$i]="` sed -n "s/DeletionDate=\(.*\)/\1/p" "$trash_folder/info/${filename[$i]}.trashinfo"`"
            echo "${filename[$i]} | ${truename[$i]} | ${deldate[$i]}"
            ((i++))
        fi
    done
)

Dernière modification par Pandark (Le 10/06/2008, à 04:28)


Pandark
99% libre…

Hors ligne

#7 Le 10/06/2008, à 05:07

Alain.g

Re : Gestion de la corbeille Nautilus par Bash

Bonjour

Une solution sans changer la valeur d'IFS :
à la place de

for residu in `ls "$trash_folder/files/"`

mettre

while read -r residu

et remplacer done par

done < <(ls "$trash_folder/files/")

On aurait pu également remplacer directement par :

ls "$trash_folder/files/" | while read -r residu

mais attention si la valeur des variables doit être conservée.

Les seuls espaces blancs qui devraient poser problème sont les sauts de ligne (très rare et déconseillé dans les noms de fichier).
Si on veut que ça fonctionne aussi avec les sauts de ligne, mettre :

while read -rd $'\0' residu

et

done < <(cd "$trash_folder/files/" ; find * -maxdepth 0 -print0)

Dernière modification par Alain.g (Le 10/06/2008, à 10:53)


Xubuntu Karmic !

Hors ligne