Last active
April 14, 2018 08:41
-
-
Save clee/6238539 to your computer and use it in GitHub Desktop.
agealyzer: given a root directory, spits out histogram of ages of files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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)))))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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