Skip to content

Instantly share code, notes, and snippets.

@clee
Last active April 14, 2018 08:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save clee/6238539 to your computer and use it in GitHub Desktop.
Save clee/6238539 to your computer and use it in GitHub Desktop.
agealyzer: given a root directory, spits out histogram of ages of files
(ns clee.agealyzer)
(require '[clojure.java.io :as io])
(defn date [x] (java.util.Date. x))
(defn is-file? [f] (.isFile f))
(defn last-modified [f] (.lastModified f))
(defn get-year [x] (.getYear x))
(defn process-dir
([dir]
(let [files (filter is-file? (file-seq (io/file dir)))]
(map (fn [x] (+ 1900 (get-year (date (last-modified x))))) files))))
(defn get-date-map
[_map, _dates]
(loop [m _map
d _dates]
(if d
(recur (let [b (first d)] (assoc m b (+ 1 (get m b 0)))) (next d))
m)))
(defn -main
"Given a directory, spits out a histogram of file ages"
([] (println "usage: agealyzer <path/to/dir>"))
([path]
(let [m (into (sorted-map) (get-date-map {} (process-dir path)))
maxValue (apply max (vals m))]
(doseq [entry m]
(let [p (* 40.0 (/ (val entry) maxValue))
pf (apply str (repeat (int p) "="))]
(println (format "%4d: |%-40s| (%d)" (key entry) pf (val entry))))))))
package main
import (
"flag"
"fmt"
"os"
"path/filepath"
"sort"
"strings"
)
func main() {
flag.Parse()
root := flag.Arg(0)
years := make(map[int]int)
filepath.Walk(root, func(path string, f os.FileInfo, err error) error {
if !f.Mode().IsRegular() {
return nil
}
year := f.ModTime().Year()
years[year]++
return nil
})
maxHits := 0
keys := []int{}
for year, hits := range years {
keys = append(keys, year)
if hits > maxHits {
maxHits = hits
}
}
sort.Ints(keys)
bar := strings.Repeat("=", 40)
for _, k := range keys {
hits := years[k]
p := int(40.0 * hits / maxHits)
fmt.Printf("%d: |%-40.*s| (%d)\n", k, p, bar, hits)
}
}
#!/usr/bin/env python
from __future__ import print_function
from sys import argv
from collections import defaultdict
from os import walk, stat
from os.path import join, isfile, islink
from time import gmtime
years = defaultdict(int)
for root, dirs, files in walk(argv[1]):
for name in files:
filename = join(root, name)
if not isfile(filename) or islink(filename):
continue
year = gmtime(stat(filename).st_mtime).tm_year
years[year] += 1
maxHits = max([years[year] for year in years])
for year in sorted(years.keys()):
hits = years[year]
print('%d: |%%-40.%ds| (%d)' % \
(year, (40.0 * hits / maxHits), hits) % ('=' * 40))
#!/usr/bin/env ruby
# ported the script to ruby (kinda) for comparison purposes
require 'find'
if ARGV.length != 1 or not File.directory? ARGV[0]
puts "usage: agealyzer.rb </path/to/dir>"
exit 1
end
years = Hash.new 0
Find.find ARGV[0] do |f|
next unless File.file? f
year = File.stat(f).mtime.year
years[year] += 1
end
years.sort.each do |year, hits|
bars = ('=' * ((60.0 * hits) / years.values.max)).ljust 60
print "#{year}: |#{bars}| (#{hits})\n"
end
extern crate chrono;
extern crate walkdir;
use std::io;
use std::env;
use std::path::Path;
use std::collections::BTreeMap;
use std::time::UNIX_EPOCH;
use std::iter::repeat;
use chrono::{UTC, TimeZone, Datelike};
use walkdir::WalkDir;
fn walk(directory: &Path) -> io::Result<BTreeMap<i32, u64>> {
let mut years: BTreeMap<i32, u64> = BTreeMap::new();
for entry in WalkDir::new(&directory) {
let meta = entry?
.path()
.symlink_metadata()?;
if !meta.is_file() {
continue;
}
if let Ok(seconds) = meta.modified()?.duration_since(UNIX_EPOCH) {
let year = UTC.timestamp(seconds.as_secs() as i64, 0).date().year();
*years.entry(year).or_insert(0) += 1;
}
}
Ok(years)
}
fn main() {
let args: Vec<String> = env::args().collect();
let directory = match args.len() {
2 => Path::new(&args[1]),
_ => panic!("usage: agealyzer </path/to/directory>"),
};
let years = walk(&directory).expect("at least an empty collection");
let max_hits = years.values().max().expect("should be at least one int");
for y in years.keys() {
let hits = years.get(&y).expect("should be a value here");
let p = (60.0 * *hits as f64) / *max_hits as f64;
let pf = repeat("=").take(p as usize).collect::<String>();
println!("{0}: |{1: <60}| ({2})", y, pf, hits);
}
}
2000: | | (2)
2003: | | (3)
2004: | | (152)
2005: | | (834)
2006: |= | (1866)
2007: |= | (2416)
2008: |== | (3834)
2009: |========================= | (33788)
2010: |=========== | (14994)
2011: |========================================| (53354)
2012: | | (1)
2013: | | (89)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment