Difference between revisions of "Prova pratica 2017.01.17"
Jump to navigation
Jump to search
m (Aggiunti testi esercizi) |
|||
(One intermediate revision by one other user 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 73: | Line 83: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Esercizio 3: | + | ==Esercizio 3:== |
− | Python | + | <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> | <syntaxhighlight lang=Python> | ||
Line 99: | Line 117: | ||
print("Mancano degli argomenti") | print("Mancano degli argomenti") | ||
</syntaxhighlight> | </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
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)