Difference between revisions of "Prova pratica 2017.01.17"

From Sistemi Operativi
Jump to navigation Jump to search
(Created page with "<syntaxhighlight lang=C> #include <stdio.h> #include <stdlib.h> #include <dirent.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> struct fileelem { dev_t ...")
 
m (Aggiunti testi esercizi)
 
(2 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 +
[http://www.cs.unibo.it/~renzo/so/pratiche/2017.01.17.pdf link al testo]
 +
==Esercizio 1==
 +
<source lang="text">
 +
Scrivere un programma che conti I file ordinari e le directory presenti nel sottoalbero della directory passata come
 +
parametro (o della directory corrente se non viene passato alcun parametro).
 +
Ogni file o directory deve venir contato una sola volta anche se e’ presente con diversi nomi a causa dei link fisici.
 +
Ogni altro tipo di file che non sia file ordinario o directory (e.g. socket, named pipe, file speciali, link simbolici)
 +
devono essere ignorati.
 +
</source>
 +
===Soluzione del prof===
 
<syntaxhighlight lang=C>
 
<syntaxhighlight lang=C>
 
#include <stdio.h>
 
#include <stdio.h>
Line 72: Line 82:
  
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
==Esercizio 3:==
 +
<source lang="text">
 +
Scrivere uno script che faccia il merge dei contenuti due directory:
 +
merge a b c
 +
Tutti i file (non le directory) esistenti in a e in b devono essere spostati in c. Nel caso due file con lo stesso nome
 +
compaiano sia in a sia in b, il file spostato in c deve essere quello piu' recentementente modificato, l’altro deve
 +
rimanere nella directory di origine.
 +
</source>
 +
===Python===
 +
====Soluzione di Ossigeno====
 +
 +
<syntaxhighlight lang=Python>
 +
def merge():  # dati due path di due directory, fa la merge in una terza directory
 +
    # 1=pathprimo 2=pathsecondo 3=pathdestinazione
 +
    if (len(sys.argv) > 3):
 +
        for d, _, fl in os.walk(sys.argv[1]):
 +
            for f in fl:
 +
                path = os.path.join(d, f)
 +
                if (os.path.isfile(path)):  # e' un file e non una directory allora copio tutto
 +
                    shutil.copy2(path, sys.argv[3])
 +
        for d, _, fl in os.walk(sys.argv[2]):
 +
            for f in fl:
 +
                path = os.path.join(d, f)
 +
                if (os.path.isfile(path)):  # e' un file e non una directory in path2
 +
                    esistenza = os.path.join(sys.argv[3], f)
 +
                    if (not os.path.isfile(esistenza)):  # se non esiste un file con quel nome
 +
                        shutil.copy2(path, sys.argv[3])
 +
                    else:
 +
                        if (os.stat(path).st_mtime > os.stat(
 +
                                esistenza).st_mtime):  # e' piu recente tempo del file in path2 rispetto a path3
 +
                            shutil.copy2(path, sys.argv[3])
 +
    else:
 +
        print("Mancano degli argomenti")
 +
</syntaxhighlight>
 +
===Bash===
 +
====Soluzione di Gabriele Calarota====
 +
<syntaxhighlight lang=Bash>
 +
#!/bin/bash
 +
 +
if [ $# -lt 3 ] ; then
 +
echo "ERROR: example merge a b c"
 +
exit 1
 +
fi
 +
 +
a=$1
 +
b=$2
 +
c=$3
 +
tmp_file=file_tmp
 +
 +
touch $tmp_file
 +
 +
 +
find $a -type f -print0 | xargs -0 basename -a >> $tmp_file
 +
find $b -type f -print0 | xargs -0 basename -a >> $tmp_file
 +
 +
#univoci
 +
#echo "UNIQ"
 +
sort $tmp_file | uniq -u | while read line
 +
do
 +
 +
#now $line contains the basename of the file
 +
ls "$a/$line" &>/dev/null && mv -v "$a/$line" "$c/$line"
 +
ls "$b/$line" &>/dev/null && mv -v "$b/$line" "$c/$line"
 +
done
 +
 +
#echo "DOUBLE"
 +
sort $tmp_file | uniq -d | while read line
 +
do
 +
#now $line contains the basename of both of the filename
 +
file1="$(stat -c %Y $a/$line)"
 +
file2="$(stat -c %Y $b/$line)"
 +
if [ $file1 -lt $file2 ] ; then
 +
#echo "$line chose from $b"
 +
mv -v "$b/$line" "$c/$line"
 +
else
 +
#echo "$line chose from $a"
 +
mv -v "$a/$line" "$c/$line"
 +
fi
 +
done
 +
 +
rm $tmp_file 
 +
</syntaxhighlight>
 +
--[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 12:17, 15 May 2017 (CEST)

Latest revision as of 15:55, 15 May 2017

link al testo

Esercizio 1

Scrivere un programma che conti I file ordinari e le directory presenti nel sottoalbero della directory passata come
parametro (o della directory corrente se non viene passato alcun parametro).
Ogni file o directory deve venir contato una sola volta anche se e’ presente con diversi nomi a causa dei link fisici.
Ogni altro tipo di file che non sia file ordinario o directory (e.g. socket, named pipe, file speciali, link simbolici)
devono essere ignorati.

Soluzione del prof

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

struct fileelem {
	dev_t dev; 
	ino_t ino;
	struct fileelem *next;
};

int addfile(struct fileelem **head, dev_t dev, ino_t ino) {
	if (*head == NULL) {
		*head = malloc(sizeof(struct fileelem));
		(*head)->dev = dev;
		(*head)->ino = ino;
		(*head)->next = NULL;
		return 1;
	} else if ((*head)->dev == dev && (*head)->ino == ino) {
		return 0;
	} else {
		return addfile(&((*head)->next), dev, ino);
	}
}

int filt(const struct dirent *elem) {
	if (strcmp(elem->d_name,".") == 0 ||
			strcmp(elem->d_name,"..") == 0)
		return 0;
	else {
		return 1;
	}
}

int recscan(char *path, struct fileelem **head) {
	struct dirent **list;
	int count = 0;
	int n = scandir(path, &list, filt, alphasort);
	int i;
	for (i = 0; i < n; i++) {
		struct stat buf;
		char *filepath;
		asprintf(&filepath,"%s/%s",path,list[i]->d_name);
		stat(filepath, &buf);
		switch (buf.st_mode & S_IFMT) {
			case S_IFREG:
				count += addfile(head, buf.st_dev, buf.st_ino);
				printf("file %s %ld %ld ... %d\n",filepath,buf.st_dev,buf.st_ino,count);
				break;
			case S_IFDIR:
				count = count + recscan(filepath, head);
				break;
		}
		free(filepath);
		free(list[i]);
	}
	free(list);
	return count;
}

int main(int argc, char *argv[]) {
	struct fileelem *head = NULL;
	int result;
	if (argc > 1)
		chdir(argv[1]);
	result = recscan(".", &head);
	printf("Num of independent files: %d\n", result);
}

Esercizio 3:

Scrivere uno script che faccia il merge dei contenuti due directory:
merge a b c
Tutti i file (non le directory) esistenti in a e in b devono essere spostati in c. Nel caso due file con lo stesso nome
compaiano sia in a sia in b, il file spostato in c deve essere quello piu' recentementente modificato, l’altro deve
rimanere nella directory di origine.

Python

Soluzione di Ossigeno

def merge():  # dati due path di due directory, fa la merge in una terza directory
    # 1=pathprimo 2=pathsecondo 3=pathdestinazione
    if (len(sys.argv) > 3):
        for d, _, fl in os.walk(sys.argv[1]):
            for f in fl:
                path = os.path.join(d, f)
                if (os.path.isfile(path)):  # e' un file e non una directory allora copio tutto
                    shutil.copy2(path, sys.argv[3])
        for d, _, fl in os.walk(sys.argv[2]):
            for f in fl:
                path = os.path.join(d, f)
                if (os.path.isfile(path)):  # e' un file e non una directory in path2
                    esistenza = os.path.join(sys.argv[3], f)
                    if (not os.path.isfile(esistenza)):  # se non esiste un file con quel nome
                        shutil.copy2(path, sys.argv[3])
                    else:
                        if (os.stat(path).st_mtime > os.stat(
                                esistenza).st_mtime):  # e' piu recente tempo del file in path2 rispetto a path3
                            shutil.copy2(path, sys.argv[3])
    else:
        print("Mancano degli argomenti")

Bash

Soluzione di Gabriele Calarota

#!/bin/bash

if [ $# -lt 3 ] ; then
	echo "ERROR: example merge a b c"
	exit 1
fi

a=$1
b=$2
c=$3
tmp_file=file_tmp

touch $tmp_file


find $a -type f -print0 | xargs -0 basename -a >> $tmp_file
find $b -type f -print0 | xargs -0 basename -a >> $tmp_file

#univoci
#echo "UNIQ"
sort $tmp_file | uniq -u | while read line
do
	
	#now $line contains the basename of the file
	ls "$a/$line" &>/dev/null && mv -v "$a/$line" "$c/$line"
	ls "$b/$line" &>/dev/null && mv -v "$b/$line" "$c/$line"
done

#echo "DOUBLE"
sort $tmp_file | uniq -d | while read line
do
	#now $line contains the basename of both of the filename
	file1="$(stat -c %Y $a/$line)"
	file2="$(stat -c %Y $b/$line)"
	if [ $file1 -lt $file2 ] ; then
		#echo "$line chose from $b"
		mv -v "$b/$line" "$c/$line"
	else
		#echo "$line chose from $a"
		mv -v "$a/$line" "$c/$line"
	fi
done

rm $tmp_file

--GabrieleCalarota (talk) 12:17, 15 May 2017 (CEST)