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 09/05/2007, à 07:43

momsse

Shell script (haut niveau)

Bonsoir, j'ai un exercice assez complexe à faire, voila l'énnoncé:

Écrire un script-shell nettoyer.sh qui supprime à partir du répertoire courant tous les fichiers dont le nom se termine
par un caractère ’∼’ (même si le nom du fichier commence par un caractère ’.’) ou dont le nom débute et se termine par un caractère ’#’ ; ces fichiers sont fréquemment des fichiers temporaires. La suppression de ces fichiers devra s’effectuer récursivement dans toute la sous-arborescence du répertoire courant et devra fonctionner même à l’intérieur des sous-répertoire dont le nom commence par un caractère ’.’. Outre l’ensemble des commandes internes au shell bash, les seules commandes externes utilisables sont dirname, basename et bien entendu rm.

Votre script-shell NE DEVRA PAS utiliser les commandes ls, find, grep ou egrep.

Cet exercice est un véritable challenge, jusqu'ici j'ai déposé le script sur pres de 3 grands forum dont je tairais le nom, aucun n'a réussi à trouver un tel script, j'avoue que je n'arrive même pas à le commencer ...

Voici ma piste (peut être fausse)

Piste:
Je pensais que l'on pouvais par exemple afficher les fichiers que l'on souhaitait avec quelque chose qui ressemblerait a :

echo */[#]*[#] .*[~] *[~]

puis les supprimer avec un for:


for elu in $(echo */[#]*[#] .*[~] *[~]);
do
rm $elu
done

Je remercie déja tous ceux qui contribueront à faire avancer le script !!

Merci d'avance

Hors ligne

#2 Le 09/05/2007, à 08:34

pef

Re : Shell script (haut niveau)

Je ne comprends vraiment pas l'intérêt de ne pas utiliser find, c'est un exercice, certes, mais dans ce cas autant trouver quelque chose qui ne peut vraiment pas être fait avec find
C'est comme si on te disais tu vois la vis là, essaye de la dévisser avec un burin et une clé de 12, mais sans utiliser de tournevis.

Sinon as-tu déjà regardé dans le advanced bash scripting ?

Dernière modification par pef (Le 09/05/2007, à 08:36)

Hors ligne

#3 Le 09/05/2007, à 08:37

momsse

Re : Shell script (haut niveau)

L'interêt ? Aucun ! A part mettre la promotion en difficulté sur l'exo final. Et rendre l'exercice assez corriace ...

Hors ligne

#4 Le 09/05/2007, à 08:42

momsse

Re : Shell script (haut niveau)

Je ne connais pas le "advanced bash scripting", qu'est ce ?

Hors ligne

#5 Le 09/05/2007, à 09:36

momsse

Re : Shell script (haut niveau)

Voila l'algorithme de la fonction récursive, c'est peut etre un peu plus claire comme ca ?



fonction chercher()
debut

dossier = $1

Pour tous les éléments du dossier
    Si (element est un fichier)   et  (element commence et fini par #)  ou  (element fini par ~)  ou  (élément commence par . et fini par ~)
           
                supprimer element
    Sinon
        Si (element est un repertoire) et (element different de . ou ..)
           
            chercher() $element
        fin si
    fin si

fin

chercher () . // On oublie pas de lancer la recherche dans le repertoire courant

Dernière modification par momsse (Le 09/05/2007, à 09:40)

Hors ligne

#6 Le 09/05/2007, à 09:52

Watchwolf

Re : Shell script (haut niveau)

tu utilise sftp et ll lol

Hors ligne

#7 Le 09/05/2007, à 11:04

kuri

Re : Shell script (haut niveau)

bon bein ca m a occupe pendant presque une heure big_smile (ca fait longtemps que j avais pas fait de shell)


function chercher() {

echo $1
for file in "$1"/*; do
	if [ -e "${file}" ]; then
	fichier=$(basename "$file")
		if [ -z $(echo ${fichier#*~}) ]; then
			rm -f $file
		fi

		if [ $(echo ${fichier:0:1}) = "#" ]; then
			if [ $(echo ${fichier:${#fichier}-1:1}) = "#" ]; then
				rm -fr $file
			fi
		fi

	fi

	if [ -d "${file}" ]; then
	chercher ${file}
	fi
done
}


dir="."
if [ ! -z ${1} ]; then
	dir=${1}
fi
chercher $dir;

Hors ligne

#8 Le 09/05/2007, à 11:18

momsse

Re : Shell script (haut niveau)

Salut ! Un énorme merci pour tout le temps que tu a passé big_smile

J'ai eu ces erreur lors du lancement:

.
./2INFA5-grange
./chercher: line 7: [: too many arguments
./chercher: line 7: [: coche: binary operator expected

Tu as bien traité les 3 cas suivant dans ton code ?

-supprimer ce qui commence et fini par # (ex: #fichier#)
-supprimer ce qui termine par ~ (ex: fichier~)
-supprimer ce qui termine par ~ et commence par . (ex: .fichier~)

Ca sera super cool que tu commente un tout petit peu le script sur les grandes lignes !!

Je te remercie encore !

Hors ligne

#9 Le 09/05/2007, à 11:21

kuri

Re : Shell script (haut niveau)

ton soucis est sur les fichiers contenant des espaces, j ai pas teste ca encore, mais bon, je t ai fais le plus gros du boulot, je pense que ca sera pas un soucis maintenant smile

les commentaires ? oui d accord, mais apres manger big_smile

ah j ai oublie les .*~
"oops"

Dernière modification par kuri (Le 09/05/2007, à 11:22)

Hors ligne

#10 Le 09/05/2007, à 13:19

kaworu

Re : Shell script (haut niveau)


"There are in order of increasing severity: lies, damn lies, statistics, and computer benchmarks."

Hors ligne

#11 Le 09/05/2007, à 13:38

kuri

Re : Shell script (haut niveau)

Ce code fonctionne pour les fichier contenant des espaces, malgres un avertissement sur le test.
Il ne prends pas en compte les fichier commancant par ".", je vois pas comment le faire sans "ls"

function chercher() {

for file in "$1"/*; do

	# Si le "fichier" est bien un fichier
	if [ -e "${file}" ]; then
		#Recupere le nom du fichier, et non son chemin d acces + nom
		fichier=`basename "$file"`

		# Ce test permet de faire un echo de la variable fichier,
		# en supprimant tous les caracteres jusqu a ~, donc si
		# le fichier contient ~, echo renvoit une chaine vide
		if [ -z `echo ${fichier#*~}` ]; then
			rm -f "$file"
		fi

		# Ce test affiche les caracteres de la variable fichier a partir
		# du caractere 0, et d'une longueur de 1 caracteres, donc
		# elle affiche le premier caractere de la chaine
		if [ `echo ${fichier:0:1}` = "#" ]; then

			# Pareil mais affiche le dernier caractere
			if [ `echo ${fichier:${#fichier}-1:1}` = "#" ]; then
				rm -fr "$file"
			fi
		fi

	fi

	# Si le "fichier" est un repertoire
	if [ -d "${file}" ]; then
	chercher ${file}
	fi
done
}

# Par defaut on cherche dans le repertoire courant
dir="."

# Si un chemin est donne en parametre, on cherche
# Dans ce repertoire au lieu du courant
if [ ! -z ${1} ]; then
	dir=${1}
fi
chercher $dir;

Hors ligne

#12 Le 09/05/2007, à 16:22

momsse

Re : Shell script (haut niveau)

merci pour l'explication, je suis assez mauvais en programation, j'ai essayer de pondre quelque chose, dit moi ce que tu en pense, ce que tu propose comme modification la dedans:

Mon prof vient de me mailer il dit qu'il faut utiliser le résultat de la commande echo comme un vecteur de variable:


function nettoyer (){

elus=$(echo * .*)

for elu in $elus;do
if [ -e $elu -a -d $elu -a $elu != ".." -a $elu != "." ]
then
    cd $elu
    nettoyer
else
   if [ $elu=".*~" -o $elu="*#" -o $elu="*~" ]
   then
   rm $elu
   fi
fi
done
}

Dernière modification par momsse (Le 09/05/2007, à 16:25)

Hors ligne

#13 Le 09/05/2007, à 16:46

kuri

Re : Shell script (haut niveau)

ton test de chaine de caractere testera reellement *~ par exemple.

prefere donc ce que j ai mis dans mon script, car toi tu veux savoir si la chaine finit par ~, et *~ ca le fera pas, ca regardera si ton fichier  s appelle *~.
le "echo * .*" je savais pas que ca sortait ca, ce qui regle le probleme des fichiers cachés

ensuite quand tu vas lancer ton script, rien ne va lancer la fonction, regarde dans la version que je t ai propose comment je declare la fonction et son code, et tout en bas, je l appelle

apres tu fais ce "echo" qui te donne donc les fichiers presents, et apres tu fais un test -e, pour savoir si le dossier existe, ca me semble superflu

edit : je reviens sur cette ligne de mon code :

            # Pareil mais affiche le dernier caractere
            if [ `echo ${fichier:${#fichier}-1:1}` = "#" ]; then

${#fichier} retourne le nombre total de caracteres, comme ca commence a 0, on fait -1 pour avoir le dernier element

Dernière modification par kuri (Le 09/05/2007, à 16:49)

Hors ligne

#14 Le 09/05/2007, à 17:10

momsse

Re : Shell script (haut niveau)

Tu pourrais essayer de modifier un peu mon code pour qu'il puisse fonctionner ?

Ce serai sympa...
Parce qu'avec ton code, le prof saura de suite que ce n'est pas de moi ...

Je te remercie d'avance !:)

Hors ligne

#15 Le 09/05/2007, à 17:18

kuri

Re : Shell script (haut niveau)

oki, faut modifier ta boucle deja car va pas, c est pas une liste de ligne mais des parametres enfin la je vais sortir du taff, je vois ca apres, dans le cas ou mon pote se decommande pour le cine de ce soir tongue

mais je vais jeter un oeil quand je peux

Hors ligne

#16 Le 09/05/2007, à 17:22

momsse

Re : Shell script (haut niveau)

J'ai exam d'USI demain 8h30, si tu peut faire ca même tard ce soir ca ne mé dérange pas, autrement te casse pas la tête a le faire demain il me servira pas à grand chose, je te remercie quand même, tu m'a beaucoup aidé aujourd'hui !

Merci encore !:D

Bon ciné ...

Hors ligne

#17 Le 09/05/2007, à 20:23

toto4455

Re : Shell script (haut niveau)

#!/bin/bash

function trouve( ) {
	
	chemin=`pwd`;
		
	 printf "%s\n" * .* > ListeFichierTxt
	
	while read  line
	do 
		elu=$line
		
		if [ -d "$elu" ]; then
			
			if [ "$elu" != "." ]  &&  [ "$elu" != ".." ] ;
			then
				cd $elu
				trouve 
				cd ..
				
			fi 
		elif [ -f "$elu" ]; then
			
			fin=`echo ${#elu}`
			fin=$(( $fin - 1 ))
			CAR="#"
			CAR2="~"
			if [ "$CAR" == "`echo ${elu:0:1}`" ] && [ "$CAR" == "`echo ${elu:$fin:1}`" ] || [ "$CAR2" == "`echo ${elu:$fin:1}`" ] ;	then
				echo "Effacer $chemin $elu" 				 
			fi		
			
		fi
	
	
	done < ListeFichierTxt
	rm ListeFichierTxt
}

trouve

#18 Le 09/05/2007, à 21:02

toto4455

Re : Shell script (haut niveau)

avec le chemin au bon endroit smile

#!/bin/bash

function trouve( ) {
		
	printf "%s\n" * .* > ListeFichierTxt
	
	while read  line
	do 
		elu=$line
		
		if [ -d "$elu" ]; then
			
			if [ "$elu" != "." ]  &&  [ "$elu" != ".." ] ;
			then
				cd $elu
				trouve 
				cd ..
				
			fi 
		elif [ -f "$elu" ]; then
			
			fin=`echo ${#elu}`
			fin=$(( $fin - 1 ))
			CAR="#"
			CAR2="~"
			chemin=`pwd`;
			if [ "$CAR" == "`echo ${elu:0:1}`" ] && [ "$CAR" == "`echo ${elu:$fin:1}`" ] || [ "$CAR2" == "`echo ${elu:$fin:1}`" ] ;	then
				echo "Effacer $chemin $elu" 				 
			fi		
			
		fi
	
	
	done < ListeFichierTxt
	rm ListeFichierTxt
}

trouve