Difference between revisions of "Prova pratica 2015.01.21"
| m (Aggiunte soluzioni da altre pagine, uniformato) | m (Aggiunta soluzione di un'altro studente) | ||
| Line 57: | Line 57: | ||
| --[[User:LeonardoF|LeonardoF]] ([[User talk:LeonardoF|talk]]) 15:39, 26 March 2017 (CEST)LeonardoF | --[[User:LeonardoF|LeonardoF]] ([[User talk:LeonardoF|talk]]) 15:39, 26 March 2017 (CEST)LeonardoF | ||
| + | |||
| + | ===Soluzione di Luca=== | ||
| + | <source lang="c"> | ||
| + | #include <stdio.h> | ||
| + | #include <unistd.h> | ||
| + | #include <stdlib.h> | ||
| + | #include <fcntl.h> | ||
| + | #include <s2argv.h> | ||
| + | #include <string.h> | ||
| + | |||
| + | int main(int argc, char *argv[]){ | ||
| + | 	int pfd[2]; | ||
| + | 	FILE *file=fopen(argv[1], "r");//apro file in lettura | ||
| + | 	char cmd1[256]; | ||
| + | 	char cmd2[256]; | ||
| + | |||
| + | 	fgets(cmd1, sizeof(cmd1), file);//memorizzo il primo comando in cmd1 | ||
| + | 	fgets(cmd2, sizeof(cmd2), file);//memorizzo il 2 comando in cmd2 | ||
| + | |||
| + | 	pipe(pfd);//creo i 2 descrittori | ||
| + | |||
| + | 	switch(fork()){ | ||
| + | 		case 0:	//figlio fornisce output | ||
| + | 			dup2(pfd[1], STDOUT_FILENO); | ||
| + | 			close(pfd[0]); | ||
| + | 			close(pfd[1]); | ||
| + | 			execsp(cmd1);  | ||
| + | 			exit(1); | ||
| + | |||
| + | 		case -1: exit(1); | ||
| + | 	} | ||
| + | 	switch(fork()){//figlio prende input | ||
| + | 		case 0:	 | ||
| + | 			dup2(pfd[0], STDIN_FILENO); | ||
| + | 			close(pfd[0]); | ||
| + | 			close(pfd[1]); | ||
| + | 			execsp(cmd2);  | ||
| + | 			exit(1); | ||
| + | |||
| + | 		case -1: exit(1); | ||
| + | 	} | ||
| + | 	int status; | ||
| + | 	close(pfd[0]); | ||
| + | 	close(pfd[1]); | ||
| + | 	wait(&status); | ||
| + | 	wait(&status); | ||
| + | 	fclose(file); | ||
| + | } | ||
| + | </source> | ||
| ==Esercizio 2== | ==Esercizio 2== | ||
| Line 430: | Line 479: | ||
| --[[User:Ale|Ale]] ([[User talk:Ale|talk]]) 14:01, 25 May 2015 (CEST) | --[[User:Ale|Ale]] ([[User talk:Ale|talk]]) 14:01, 25 May 2015 (CEST) | ||
| + | ===Soluzione di Luca=== | ||
| + | <source lang="c">#include <stdio.h> | ||
| + | #include <stdio.h> | ||
| + | #include <unistd.h> | ||
| + | #include <stdlib.h> | ||
| + | #include <fcntl.h> | ||
| + | #include <s2argv.h> | ||
| + | #include <string.h> | ||
| + | |||
| + | int main(int argc, char *argv[]){ | ||
| + | 	int pfd[2], num_righe=0, tmp=0; | ||
| + | 	FILE *file=fopen(argv[1], "r");//apro file in lettura | ||
| + | 	char buff[256]; | ||
| + | 	pipe(pfd); | ||
| + | |||
| + | 	while(fgets(buff, sizeof(buff), file)!=NULL){//calcolo il numero di righe del file | ||
| + | 		num_righe++; | ||
| + | 	} | ||
| + | 	char comandi[num_righe][256];//array di stringhe | ||
| + | 	rewind(file); | ||
| + | |||
| + | 	for(tmp=0; tmp<num_righe; tmp++){ | ||
| + | 		fgets(comandi[tmp], sizeof(comandi[tmp]), file);//copio ogni comando per riga | ||
| + | 		//printf("comando num %d: %s\n", tmp, comandi[tmp]); | ||
| + | 		switch(fork()){ | ||
| + | 			case 0:	 | ||
| + | 				if(tmp<num_righe-1){ | ||
| + | 					dup2(pfd[1], STDOUT_FILENO); | ||
| + | 					close(pfd[0]); | ||
| + | 					close(pfd[1]); | ||
| + | 					execsp(comandi[tmp]);  | ||
| + | 					exit(1); | ||
| + | 				} | ||
| + | 				if(tmp==num_righe-1){ | ||
| + | 					dup2(pfd[0], STDIN_FILENO); | ||
| + | 					close(pfd[0]); | ||
| + | 					close(pfd[1]); | ||
| + | 					execsp(comandi[tmp]);  | ||
| + | 					exit(1); | ||
| + | 				} | ||
| + | 			case -1: exit(1); | ||
| + | |||
| + | 		} | ||
| + | 	} | ||
| + | 	int status; | ||
| + | 	close(pfd[0]); | ||
| + | 	close(pfd[1]); | ||
| + | 	for(tmp=0; tmp<num_righe; tmp++) | ||
| + | 		wait(&status); | ||
| + | 	fclose(file); | ||
| + | } | ||
| + | </source> | ||
| ==Esercizio 3== | ==Esercizio 3== | ||
| Line 572: | Line 673: | ||
| '''perché proporre una soluzione in un linguaggio che non ho ancora spiegato?'''[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 19:36, 21 November 2016 (CET) | '''perché proporre una soluzione in un linguaggio che non ho ancora spiegato?'''[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 19:36, 21 November 2016 (CET) | ||
| + | |||
| + | ===Soluzione di Luca(Bash)=== | ||
| + | <source lang="bash"> | ||
| + | #! /bin/bash | ||
| + | trova () { | ||
| + |    find $1 -type f -exec md5sum {} \; | sort > md5.txt #calcola l'md5 di tutto il sottoalbero, lo ordina e lo salva in un file | ||
| + |    cat md5.txt | grep "`cut -d ' ' -f 1 md5.txt | uniq -d`" #stampa le righe del file, nelle quali in primo campo ha valore(md5) duplicato  | ||
| + | } | ||
| + | |||
| + | if [[ $# -eq 0 ]] ; then #se num argomenti è 0 | ||
| + |    trova | ||
| + | else | ||
| + |    for parametro in $* #chiamo la funzione per ogni argomento | ||
| + |    do | ||
| + |       trova $parametro | ||
| + |    done | ||
| + | fi | ||
| + | exit | ||
| + | </source> | ||
Latest revision as of 08:25, 10 May 2017
Testo: [1]
Esercizio 1
Soluzione di Leonardo F
//ESERCIZIO 1
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "execs.h" // from https://github.com/rd235/s2argv-execs
#define BUFFLEN  4096 //probably there is a system constant
int main(int argc,const char* argv[]){
	//take the path name and open the file
	FILE* fd = fopen(argv[1],"r");
	//read the the file and put its content in a array of pointers
	char commands[2][BUFFLEN]; //migliorabile
	char buffer[BUFFLEN];
	int i = 0;
	while (fgets(buffer,sizeof(buffer),fd) != NULL){
		strcpy(commands[i],buffer);
		i ++;
	}
	//printf("%s\n%s\n",commands[0],commands[1] );
	//create a pipe
	int fpipe[2];
	pipe(fpipe); //0 reading,1 writing
	//fork
	int pid;
	pid = fork();
	switch (pid){
	case 0 : //children
		
		close(fpipe[0]);
		//children's stout = pipe output
		dup2(fpipe[1],STDOUT_FILENO);
		close(fpipe[1]);
		//execution of the command
		execsp(commands[0]);
		
		exit(-1); // in case of execsp failure
	default : //parent
		
		close(fpipe[1]);
		//father's stdin = pipe input
		dup2(fpipe[0],STDIN_FILENO);
		close(fpipe[0]);
		//receive the comnmand
		execsp(commands[1]);
		
		exit(-1);
	}	
}
--LeonardoF (talk) 15:39, 26 March 2017 (CEST)LeonardoF
Soluzione di Luca
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <s2argv.h>
#include <string.h>
 
int main(int argc, char *argv[]){
	int pfd[2];
	FILE *file=fopen(argv[1], "r");//apro file in lettura
	char cmd1[256];
	char cmd2[256];
 
	fgets(cmd1, sizeof(cmd1), file);//memorizzo il primo comando in cmd1
	fgets(cmd2, sizeof(cmd2), file);//memorizzo il 2 comando in cmd2
 
	pipe(pfd);//creo i 2 descrittori
 
	switch(fork()){
		case 0:	//figlio fornisce output
			dup2(pfd[1], STDOUT_FILENO);
			close(pfd[0]);
			close(pfd[1]);
			execsp(cmd1); 
			exit(1);
 
		case -1: exit(1);
	}
	switch(fork()){//figlio prende input
		case 0:	
			dup2(pfd[0], STDIN_FILENO);
			close(pfd[0]);
			close(pfd[1]);
			execsp(cmd2); 
			exit(1);
 
		case -1: exit(1);
	}
	int status;
	close(pfd[0]);
	close(pfd[1]);
	wait(&status);
	wait(&status);
	fclose(file);
}
Esercizio 2
Soluzione di LeonardoF
//ESERCIZIO 2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "execs.h" // from https://github.com/rd235/s2argv-execs
 
#define AOS_LENSTEP 8
 
/*
 * Define a struct for managing and array of pointer to strings.
 */
struct array_of_strings {
    char **strings;
    size_t currentlength; //the length of number of string in memory
    size_t arraylength; //the length of memory allocated
};
 
typedef struct array_of_strings array_of_strings;
 
void array_of_strings_add(array_of_strings *arrayOfStrings, char *string) {
    //if there is not enough space for the string increase it
    if (arrayOfStrings->currentlength >= arrayOfStrings->arraylength) {
        //increase the array length by the size of a string pointer
        size_t newlength = arrayOfStrings->arraylength + AOS_LENSTEP;
        //reallocate the arrayOfString with the new size
        char **new_string = realloc(arrayOfStrings->strings, newlength * sizeof(arrayOfStrings->strings[0]));
        //if the reallocation is successful
        if (new_string != NULL) {
            arrayOfStrings->arraylength = newlength;
            arrayOfStrings->strings = new_string;
        }
    }
    //if there is enough space for the string insert it
    if (arrayOfStrings->currentlength < arrayOfStrings->arraylength)
        //strdup return a pointer to a duplicate of the string
        arrayOfStrings->strings[arrayOfStrings->currentlength++] = strdup(string);
}
 
void array_of_strings_print(array_of_strings *v) {
    size_t i;
    for (i = 0; i < v->currentlength; i++)
        printf("[%3lu]: %s\n", i, v->strings[i]);
}
int main(int argc, char *argv[]) {
	int commandNumber= 0;
    char* line = NULL;
    size_t lineLength = 0;
    ssize_t numberOfCharactersRead;
    static array_of_strings arrayOfStrings;
    FILE* fd = fopen(argv[1],"r");
    while ((numberOfCharactersRead = getline(&line, &lineLength, fd)) >= 0) {
        if (line[numberOfCharactersRead - 1] == '\n')
            line[numberOfCharactersRead - 1] = 0;
        array_of_strings_add(&arrayOfStrings, line);
        commandNumber ++;
    }
 	free(line);
 	//array_of_strings_print(&arrayOfStrings);
 	//printf("%d\n",commandNumber );
 	//open the pipe
 	int fpipe[2];
	pipe(fpipe); //0 reading,1 writing
	int i = 0;
	
 	while(commandNumber > 0 ){
 		if(commandNumber > 1) {
 			int pid = fork();
 			switch(pid){
 				case 0: //children
 						close(fpipe[0]);
						//children's stout = pipe output
						dup2(fpipe[1],STDOUT_FILENO);
						close(fpipe[1]);
						//execution of the command
						//usleep( commandNumber* 1000000);
						execsp(arrayOfStrings.strings[i]);
				
						
 						exit(-1);
 				default: //parent 
 						commandNumber --;
 						i ++;
 						break;
 			}
 		}
 		else{ //last command
 				close(fpipe[1]);
				//father's stdin = pipe input
				dup2(fpipe[0],STDIN_FILENO);
				close(fpipe[0]);
				//receive the comnmand
				execsp(arrayOfStrings.strings[i]);
				
 		}
 	}
    
}
--LeonardoF (talk) 15:39, 26 March 2017 (CEST)LeonardoF
Soluzione di Stefano.zaniboni
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <error.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
   int mypipe[2];
   FILE *stream;
   char *line=NULL;
   size_t len=0;
   ssize_t read;
   /*controllo il numero degli argomenti passati*/
   if(argc != 2){
      fprintf(stderr, "no such arguments \n");
      exit(1);
   }
   /*apro il file in sola lettura*/
   stream=fopen(argv[1], "r");
   if(stream==NULL){
      exit(EXIT_FAILURE);
   }
   /*apro la pipe*/
   if(pipe(mypipe) == -1){
      fprintf(stderr, "Error pipe\n");
      exit (1);
   }
   if(fork()==0){
      close(1); /*chiudo lo stdout*/
      dup(mypipe[1]); /*rimpiazzo lo stdout con la pipe*/
      close(mypipe[0]); /*chiudo la read della pipe*/
      close(mypipe[1]);
      read=getline(&line, &len, stream);
      char *lines[2]={line, NULL};
      execvp(argv[1], lines);
      perror("execvp failed");
      exit (1);
   }
   if(fork()==0){
      close(0); /*chiudo lo stdin*/
      dup(mypipe[0]); /*rimpiazzo lo stdin con la pipe read*/
      close(mypipe[1]); /*chiudo la write della pipe*/
      close(mypipe[0]);
      read=getline(&line, &len, stream);
      execvp(argv[1], &line);
      perror("execvp 2 failed");
      exit (1);
   }
   close(mypipe[0]);
   close(mypipe[1]);
   wait(0);
   wait(0);
   free(line);
   fclose(stream);
   exit (0);
}
Il codice ho provato a testarlo ma la shell mi restituisce sempre su entrambe le exec "Permission Denied".
Nota del Prof: execvp(argv[1], &line) tenta di eseguire il file di testo (argv[1]) Renzo (talk) 16:04, 7 April 2015 (CEST)
Soluzione di AleZ
Nota: ho messo la soluzione di questo esercizio solamente perché non ne ho trovata sulla wiki una versione funzionante. Non so se sia stato corretto in classe e/o se sia stato già postato da qualche altra parte. Nel caso mi scuso.
Due versioni: una utilizzando la libreria s2argv e la funzione getline, l'altra senza entrambe.
Versione 1 (con s2argv e getline)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "/home/alessandro/Scrivania/s2argv/s2argv.h"
int main(int argc, char *argv[]) {
	//check arguments
	if (argc != 2) {
		fprintf(stderr, "Error: Expected 1 parameter.\n"
			"Usage: %s <pathname>\n", argv[0]);
		return(EXIT_FAILURE);
	}
	FILE *f;
	size_t n;
	int fd[2];
	char *command = NULL;
	f = fopen(argv[1], "rt");
	//get first command
	getline(&command, &n, f);
	//create the pipe
	if (pipe(fd) == -1) {
		perror("pipe");
		return(EXIT_FAILURE);
	}
	//create child process
	switch (fork()) {
		case -1:
		perror("fork");
		break;
		case 0:	//child process
		close(fd[0]);
		dup2(fd[1], STDOUT_FILENO); //redirect STDOUT to write to fd[1]->fd[0]
		execsp(command);
		return(EXIT_FAILURE);
		default:
		close(fd[1]);
		dup2(fd[0], STDIN_FILENO);	//redirect STDIN to read from fd[0]<-fd[1]
		wait(NULL);	//wait for child to terminate
		lseek (fd[1], 0, SEEK_SET);	//reposition STDOUT read offset to the start
		free(command);
		command = NULL;
		getline(&command, &n, f);	//get second command
		execsp(command);
		return(EXIT_FAILURE);
	}
}
Versione 2 (senza s2argv e getline)
Nota 2: Nella versione senza s2argv e getline, tutto funziona, però ho un "problema" incredibilmente strano: se cancello la variabile char sono_forse_inutile[4096] dichiarata a riga 48, a run-time il programma restituisce segmentation fault. Quella variabile era stata introdotta in precedenza inizialmente per diversa scelta implementativa, e in seguito mantenuta per scopi di debug. Terminata la sua utilità, avevo pensato di rimuoverla, ma a quanto pare non mi è permesso, e il motivo mi sfugge davvero.
La funzione fsplit è stata realizzata prendendo largamente spunto da un'altra funzione trovata su stackoverflow.
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
char **fsplit(char **res, char str[]) {
	char *p = strtok(str, " ");
	int n_spaces = 0;
	/* split string and append tokens to "res" */
	while (p) {
		n_spaces++;
		res = realloc(res, sizeof(char*) * n_spaces);
		if (res == NULL)
			exit(EXIT_FAILURE);	//allocation failed
		res[n_spaces - 1] = p;
		p = strtok(NULL, " ");
	}
	/* realloc one extra element for the last NULL */
	res = realloc(res, sizeof(char*) * (n_spaces + 1));
	res[n_spaces] = NULL;
	// debug purpose
	/* int i;
	for (i = 0; i < (n_spaces + 1); i++) {
		printf ("res[%d] = %s\n", i, res[i]);
	}*/
	return res;
}
int main (int argc, char* argv[]) {
	//check arguments
	if (argc != 2) {
		fprintf(stderr, "Error: Expected 1 parameter.\n"
			"Usage: %s <pathname>\n", argv[0]);
		return(EXIT_FAILURE);
	}
	char *pathname = argv[1];
	FILE *f;
	struct stat f_info;
	char command_one[100], command_two[100], sono_forse_inutile[4096];
	int fd[2], file_desc_out;
	pid_t pid;
	f = fopen(pathname, "rt");
	//check if file exists
	if(lstat(pathname, &f_info) == -1) {
		perror("stat");
		return(EXIT_FAILURE);
	}
	//read the commands from the first two lines - ignore the other lines
	if ( (fgets(command_one, 100, f) == NULL) ||
		(fgets(command_two, 100, f) == NULL) ) {
		fprintf(stderr, "Error while reading text from %s.", argv[1]);
	}
	fclose(f);
	//remove the \n patterns from the command strings
	strtok(command_one, "\n");
	strtok(command_two, "\n");
	/*split the command strings in arrays, where
		- comm[0] is the command
		- comm[1], comm[2], etc, are the arguments*/
	char **commv_1 = fsplit(commv_1, command_one);
	char **commv_2 = fsplit(commv_2, command_two);
	//create the pipe
	//remember: fd[0] reads and fd[1] writes
	if (pipe(fd) == -1) {
		perror("pipe");
		return(EXIT_FAILURE);
	}
	//create the child and get its pid
	if ( (pid = fork()) == -1) {
		perror("fork");
		return(EXIT_FAILURE);
	}
	if (pid == 0) {	//child
		dup2(fd[1], STDOUT_FILENO);	//connect pipe from execvp to standard output
		close(fd[0]);	//close read side from parent
		execvp(commv_1[0], commv_1);
		perror(commv_1[0]);
		return(EXIT_FAILURE);
	} else {
		close(fd[1]);	//close write side from child
		dup2(fd[0], file_desc_out);
		char *path;
		// obtain absolute path of the reader-side file descriptor of the pipe
		realpath("/proc/self/fd/file_desc_out", path);
		commv_2[1] = path;	//set the obtained path as argument for command 2
		wait(NULL);	//wait for child to terminate
	}
	execvp(commv_2[0], commv_2);
	perror(commv_2[0]);
	return(EXIT_FAILURE);
}
--Ale (talk) 14:01, 25 May 2015 (CEST)
Soluzione di Luca
#include <stdio.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <s2argv.h>
#include <string.h>
int main(int argc, char *argv[]){
	int pfd[2], num_righe=0, tmp=0;
	FILE *file=fopen(argv[1], "r");//apro file in lettura
	char buff[256];
	pipe(pfd);
	
	while(fgets(buff, sizeof(buff), file)!=NULL){//calcolo il numero di righe del file
		num_righe++;
	}
	char comandi[num_righe][256];//array di stringhe
	rewind(file);
	
	for(tmp=0; tmp<num_righe; tmp++){
		fgets(comandi[tmp], sizeof(comandi[tmp]), file);//copio ogni comando per riga
		//printf("comando num %d: %s\n", tmp, comandi[tmp]);
		switch(fork()){
			case 0:	
				if(tmp<num_righe-1){
					dup2(pfd[1], STDOUT_FILENO);
					close(pfd[0]);
					close(pfd[1]);
					execsp(comandi[tmp]); 
					exit(1);
				}
				if(tmp==num_righe-1){
					dup2(pfd[0], STDIN_FILENO);
					close(pfd[0]);
					close(pfd[1]);
					execsp(comandi[tmp]); 
					exit(1);
				}
			case -1: exit(1);
		}
	}
	int status;
	close(pfd[0]);
	close(pfd[1]);
	for(tmp=0; tmp<num_righe; tmp++)
		wait(&status);
	fclose(file);
}
Esercizio 3
Soluzione di LeonardoF bash
#!/bin/bash
#ESERCIZIO 3
find $1 -exec md5sum {} \; |sort | uniq  --all-repeated=separate --check-chars=32
shift 
for i in $@ ; do
	find $1 -exec md5sum {} \; |sort | uniq  --all-repeated=separate --check-chars=32
	shift
done
--LeonardoF (talk) 15:39, 26 March 2017 (CEST)LeonardoF
Soluzione di LeonardoF script Python
#!/usr/bin/env python3
#ESERCIZIO 3
import sys
# os.syscall way to use linux syscalls
import os
import hashlib
dictionary = {}
def add(md5val,path):
	"""function that insert the given file path in a dictionary
	using as key the given md5sum"""	
	#in this way i avoid duplicates
	dictionary.setdefault(md5val,set()).add(path)
	
def md5add(path):
	"""function that takes a filepath and calculate is md5sum
	then it calls a function to insert the file in a dictionary"""
	md5val = hashlib.md5()
	with open(path, "rb") as f:
		#Note that sometimes you won't be able to fit the whole file in memory. 
		#In that case, you'll have to read chunks of 4096 bytes sequentially and feed them to the Md5 function:
		for chunk in iter(lambda: f.read(4096), b""):
			md5val.update(chunk)
	add(md5val.hexdigest(),path)
def movmd5add(path):
	"""recursive fuction that moves in the file system and call the mdadd function
	it takes a path in input (main checks the path given by the user) """
	for root, dirs, files in os.walk(path):
		for f in files:
			#if file call the function for the md5sum 
			md5add(os.path.join(root,f)) # os.path.join(root,f)
def printdict():
	"""funtion that prints the dictionary"""
	for x in dictionary:
		#doesn't print single lines
		if len(dictionary[x]) > 1 :
			print('\r')
			for y in dictionary[x]:
				print(x," : ",y)
def main(args):
	"""main checks the path and call the functions"""
	if len(args) < 1:
		args = "."
	for path in args:
		movmd5add(path)
	printdict()
if __name__ == "__main__":
		main(sys.argv[1:])
--LeonardoF (talk) 15:39, 26 March 2017 (CEST)LeonardoF
Soluzione di S.G python
#!/usr/bin/python
"""
Esercizio 3: Script bash o Python: (10 punti):
Scrivere un programma python o uno script bash che scandisca il sottoalbero relativo alle directory passate come
parametri (o alla direcotry corrente se non ci sono parametri) e fornisca in output l'elenco dei file che hanno la
stessa somma MD5 (i.e. l'output del comando md5sum).
In output ogni riga deve mostrare un elenco di pathname realtivi a file che hanno la stessa somma MD5 (che quindi
sono molto molto probabilmente uguali).
"""
import sys
import os
import hashlib
def sha1sum(root, filename):
    sha1 = hashlib.sha1()
    with open(os.path.join(root, filename), "rb") as thefile:
        buf = thefile.read()
        sha1.update(buf)
    return sha1.hexdigest()
def initSha1vect(path):
    """ Inizializza il dizionario utilizzando come chiave il sha1
    del file, e come valore il percorso del file. """
    shafiles = {}
    for root, dirs, files in os.walk(path):
        for file in files:
            shaKey = sha1sum(root, file)
            shafiles.setdefault(shaKey, [])
            shafiles[shaKey].append(file)
    return shafiles
def main(args):
    for path in args:
        msg = True
        print "\n", path
        shafiles = initSha1vect(path)
        for k in shafiles:
            if len(shafiles[k]) > 1:
                msg = False
                print k, "\t", shafiles[k]
        if msg:
            print "Nessun file con lo stesso sha1"
if __name__ == "__main__":
	main(sys.argv[1:])
S.G (talk) 14:39, 18 November 2016 (CET)
Ho scritto una possibile soluzione dell'esercizio 3
perché proporre una soluzione in un linguaggio che non ho ancora spiegato?Renzo (talk) 19:36, 21 November 2016 (CET)
Soluzione di Luca(Bash)
#! /bin/bash
trova () {
   find $1 -type f -exec md5sum {} \; | sort > md5.txt #calcola l'md5 di tutto il sottoalbero, lo ordina e lo salva in un file
   cat md5.txt | grep "`cut -d ' ' -f 1 md5.txt | uniq -d`" #stampa le righe del file, nelle quali in primo campo ha valore(md5) duplicato 
}
if [[ $# -eq 0 ]] ; then #se num argomenti è 0
   trova
else
   for parametro in $* #chiamo la funzione per ogni argomento
   do
      trova $parametro
   done
fi
exit