Προς το περιεχόμενο

file progress graph


Προτεινόμενες αναρτήσεις

Δημοσ.

Έτσι όπως πήγες να το κάνεις ήθελες πολλάπλά '-name filename1 -name filename2 ...'. Ίσως να γίνεται με xargs αυτό (δηλαδή μια κλήση της find για κάθε αρχείο), αλλά νομίζω ότι αυτό που προτείνω είναι καλύτερο γιατί σου επιτρέπει να έχεις κοινά ονόματα αρχείων σε διαφορετικούς φακέλους.

Με xargs ήταν το τελευταίο που δοκίμασα πριν κάνω ποστ αλλά κάπου κάτι δε μου έβγαινε.

Όντως η λύση σου είναι πολύ καλύτερη!

Δημοσ.

Πολύ γρήγορα (και πρόχειρα) έφτιαξα το παρακάτω proof of concept το οποίο ψάχνει σε δύο φακέλους για κοινά αρχεία και δημιουργεί ένα progress graph των αρχείων βάσει των timestamps τους. Σκοπός βέβαια είναι να μπορεί να δέχεται σαν όρισμα παραπάνω από 2 φακέλους, αλλά θέλει ψάξιμο. Κάθε ιδεα καλοδεχούμενη.   

 

Setup ένα dummy testbed

mkdir filegraph
cd !$
mkdir testdir1
mkdir testdir2
touch testdir1/foo1
touch testdir1/foo2
touch testdir1/foo3
touch -m 01012017 testdir2/foo1
touch -m 01022017 testdir2/foo2
touch -m 01032017 testdir2/foo3

filegraph.sh

#!/bin/bash
 
#compare dirs for common filenames
c=$(comm -12 <(ls -F $1) <(ls -F $2))

#find in which dir they live in
for i in $c; do
f=$(find . -name $i -printf '%P %Td-%Tm-%TY %TH:%TM:%.2TS\t\n' | sort -r)
echo "$f" >> filegraph.dat
echo "$f"
done

filegraph.py

import networkx as nx
from networkx.drawing.nx_pydot import write_dot
import matplotlib.pyplot as plt
 
file_list = open('filegraph.dat').read().splitlines()
G=nx.Graph()
 
l = 1
for file in file_list:
    G.add_node(file, posxy=(l,l))
    l = l + 1
 
G.nodes(data=True)
for i in xrange(0,len(file_list),2):
    G.add_edge(file_list[i],file_list[i+1])
 
positions = nx.get_node_attributes(G,'posxy')
nx.draw(G, positions, node_size=2000, arrows=True, with_labels=True)
plt.savefig("filegraph.png")
plt.show()

Πρώτα τρέχουμε το filegraph.sh:

./filegraph.sh testdir1 testdir2

και στη συνέχεια το filegraph.py που δημιουργεί το file graph.

post-116013-0-44247500-1486871317_thumb.png

Δημοσ.

Για δοκίμασε αυτό:

 

1. Δημιουργία αρχείων σε 3 directories

 

 

$ cat bootstrap.sh

#!/bin/bash
# remove existing project
rm -rf proj*
# create project structure
mkdir -p proj{1,2,3}/dir{1,2,3}/
# create source files
touch proj{1,2,3}/dir{1,2,3}/source{1,2}
touch proj{1,3}/dir1/source3
touch proj{1,2}/dir2/source3
touch proj3/dir3/source3

 

2. Αλλαγή του mtime

 

 

import os
import random
import pathlib

random.seed(1)      # Reproducible results

def get_filepaths(path):
    """ Return an iterator with all the files under `path`. """
    for root, dirs, filenames in os.walk(path):
        root = pathlib.Path(root)
        for filename in filenames:
            yield root / filename

def set_mtimes():
    for project in ("proj1", "proj2", "proj3"):
        for filepath in get_filepaths(project):
            timestamp = random.randrange(1486983000, 1486984000)
            os.utime(filepath, (timestamp, timestamp))

    # let's make a single file to have the same access time in all project directories
    common_timestamp = random.randrange(1486983000, 1486984000)
    for filepath in ("proj1/dir1/source1", "proj2/dir1/source1", "proj3/dir1/source1"):
        os.utime(filepath, (common_timestamp, common_timestamp))

set_mtimes()

 

3. Εύρεση του «source file progress».

 

 

import os
import pprint
import pathlib
from operator import itemgetter
from collections import defaultdict

def get_filepaths(path):
    """ Return an iterator with all the files under `path`. """
    for root, _, filenames in os.walk(path):
        root = pathlib.Path(root)
        for filename in filenames:
            yield root / filename

class Project(object):
    def __init__(self, root):
        self.root = pathlib.Path(root)
        self.relative_paths = {p.relative_to(root): p.stat().st_mtime for p in get_filepaths(root)}

def get_all_relative_paths(projects):
    all_relative_paths = set()
    for project in projects:
        all_relative_paths.update(project.relative_paths.keys())
    return all_relative_paths

def get_source_file_progress(projects, all_relative_paths):
    source_file_progress = defaultdict(list)
    for relative_path in all_relative_paths:
        for project in projects:
            if relative_path in project.relative_paths:
                absolute_path = project.root / relative_path
                source_file_progress[relative_path].append((absolute_path, absolute_path.stat().st_mtime))
        source_file_progress[relative_path].sort(key=itemgetter(1))   # works inplace
    return source_file_progress

def main():
    projects = [Project(project_path) for project_path in PROJECTS]
    all_relative_paths = get_all_relative_paths(projects)
    source_file_progress = get_source_file_progress(projects, all_relative_paths)
    pprint.pprint(source_file_progress, width=120)

PROJECTS = ["proj1", "proj2", "proj3"]

if __name__ == "__main__":
    main()

 

Βγάζει κάτι τέτοιο. Το τι θα κάνεις τώρα με αυτό (graphs, diffs κτλ), δικό σου πρόβλημα :P

 

 

defaultdict(<class 'list'>,
            {PosixPath('dir1/source1'): [(PosixPath('proj1/dir1/source1'), 1486983622.0),
                                         (PosixPath('proj2/dir1/source1'), 1486983622.0),
                                         (PosixPath('proj3/dir1/source1'), 1486983622.0)],
             PosixPath('dir1/source2'): [(PosixPath('proj1/dir1/source2'), 1486983261.0),
                                         (PosixPath('proj2/dir1/source2'), 1486983388.0),
                                         (PosixPath('proj3/dir1/source2'), 1486983399.0)],
             PosixPath('dir1/source3'): [(PosixPath('proj1/dir1/source3'), 1486983064.0),
                                         (PosixPath('proj3/dir1/source3'), 1486983855.0)],
             PosixPath('dir2/source1'): [(PosixPath('proj2/dir2/source1'), 1486983667.0),
                                         (PosixPath('proj1/dir2/source1'), 1486983782.0),
                                         (PosixPath('proj3/dir2/source1'), 1486983914.0)],
             PosixPath('dir2/source2'): [(PosixPath('proj3/dir2/source2'), 1486983029.0),
                                         (PosixPath('proj2/dir2/source2'), 1486983483.0),
                                         (PosixPath('proj1/dir2/source2'), 1486983821.0)],
             PosixPath('dir2/source3'): [(PosixPath('proj2/dir2/source3'), 1486983460.0),
                                         (PosixPath('proj1/dir2/source3'), 1486983867.0)],
             PosixPath('dir3/source1'): [(PosixPath('proj3/dir3/source1'), 1486983499.0),
                                         (PosixPath('proj1/dir3/source1'), 1486983582.0),
                                         (PosixPath('proj2/dir3/source1'), 1486983779.0)],
             PosixPath('dir3/source2'): [(PosixPath('proj3/dir3/source2'), 1486983096.0),
                                         (PosixPath('proj1/dir3/source2'), 1486983137.0),
                                         (PosixPath('proj2/dir3/source2'), 1486983507.0)],
             PosixPath('dir3/source3'): [(PosixPath('proj3/dir3/source3'), 1486983214.0)]})

 

Παίζοντας ελαφρά με την get_file_progress() μπορείς να την κάνεις να κάνει handle τα duplicates, χάνοντας όμως σε εποπτεία:

 

 

def get_source_file_progress(projects, all_relative_paths):
    source_file_progress = defaultdict(dict)
    for relative_path in all_relative_paths:
        for project in projects:
            if relative_path in project.relative_paths:
                absolute_path = project.root / relative_path
                source_file_progress[relative_path][absolute_path.stat().st_mtime] = absolute_path
    return source_file_progress
defaultdict(<class 'dict'>,
            {PosixPath('dir1/source1'): {1486983622.0: PosixPath('proj3/dir1/source1')},
             PosixPath('dir1/source2'): {1486983261.0: PosixPath('proj1/dir1/source2'),
                                         1486983388.0: PosixPath('proj2/dir1/source2'),
                                         1486983399.0: PosixPath('proj3/dir1/source2')},
             PosixPath('dir1/source3'): {1486983064.0: PosixPath('proj1/dir1/source3'),
                                         1486983855.0: PosixPath('proj3/dir1/source3')},
             PosixPath('dir2/source1'): {1486983667.0: PosixPath('proj2/dir2/source1'),
                                         1486983782.0: PosixPath('proj1/dir2/source1'),
                                         1486983914.0: PosixPath('proj3/dir2/source1')},
             PosixPath('dir2/source2'): {1486983029.0: PosixPath('proj3/dir2/source2'),
                                         1486983483.0: PosixPath('proj2/dir2/source2'),
                                         1486983821.0: PosixPath('proj1/dir2/source2')},
             PosixPath('dir2/source3'): {1486983460.0: PosixPath('proj2/dir2/source3'),
                                         1486983867.0: PosixPath('proj1/dir2/source3')},
             PosixPath('dir3/source1'): {1486983499.0: PosixPath('proj3/dir3/source1'),
                                         1486983582.0: PosixPath('proj1/dir3/source1'),
                                         1486983779.0: PosixPath('proj2/dir3/source1')},
             PosixPath('dir3/source2'): {1486983096.0: PosixPath('proj3/dir3/source2'),
                                         1486983137.0: PosixPath('proj1/dir3/source2'),
                                         1486983507.0: PosixPath('proj2/dir3/source2')},
             PosixPath('dir3/source3'): {1486983214.0: PosixPath('proj3/dir3/source3')}})

 

  • Like 1
Δημοσ.

Α είσαι ωραίος! Μόλις κολλήσω το graph (ίσως και diffs) θα ποστάρω.

 

(ΥΓ Γιατί python code για την αλλαγή του mtime και όχι απλά $ touch -m 01012017 proj1/source1 ;;  

Δημοσ.

Για να είναι ρεαλιστικό το test case (random times κτλ) :P

 

ΥΓ. Αντικειμενικά μιλώντας, ηταν πιο σύντομο να τα κάνω hardcode, αλλά αφενος ήθελα να το κάνω με loop και αφετέρου ποτέ δεν θυμάμαι τη σύνταξη του bash :P

  • Like 1

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...