मैं एक डिस्क स्पेस रिपोर्ट कर रहा हूं जो निर्देशिका पेड़ में संचयी आकार एकत्र करने के लिए File::Find
का उपयोग करता है।JSON डेटा संरचना में फ़ाइल पथ
File::Find
से मुझे क्या मिलता है (आसानी से) निर्देशिका का नाम है।
उदा .:
/path/to/user/username/subdir/anothersubdir/etc
मैं File::Find
चल रहा हूँ के नीचे आकार इकट्ठा करने के लिए:
/path/to/user/username
और निर्देशिका का संचयी आकार रिपोर्ट और उप निर्देशिकाओं में से प्रत्येक के निर्माण।
क्या मैं वर्तमान में मिल गया है है: (। और हाँ, मुझे पता है कि बहुत अच्छा नहीं है)
while ($dir_tree) {
%results{$dir_tree} += $blocks * $block_size;
my @path_arr = split ("/", $dir_tree);
pop (@path_arr);
$dir_tree = join ("/", @path_arr);
}
।
ऐसा करने का उद्देश्य तब होता है जब मैं stat
प्रत्येक फ़ाइल में, मैं इसे वर्तमान नोड और पेड़ में प्रत्येक पैरेंट नोड में आकार जोड़ता हूं।
यह उत्पन्न करने के लिए पर्याप्त है:
username,300M
username/documents,150M
username/documents/excel,50M
username/documents/word,40M
username/work,70M
username/fish,50M,
username/some_other_stuff,30M
लेकिन अब मैं JSON को चालू करने के लिए है कि में और अधिक इस तरह करना चाहते हैं:
{
"name" : "username",
"size" : "307200",
"children" : [
{
"name" : "documents",
"size" : "153750",
"children" : [
{
"name" : "excel",
"size" : "51200"
},
{
"name" : "word",
"size" : "81920"
}
]
}
]
}
क्योंकि मैं एक डी 3 करने के लिए इच्छुक हूँ कि इस संरचना का विज़ुअलाइजेशन - D3 Zoomable Circle Pack
तो मेरा प्रश्न यह है - मेरे डेटा को एकत्र करने का सबसे अच्छा तरीका क्या है कि मैं संचयी (और आदर्श गैर cu संचयी) आकार की जानकारी, लेकिन एक हैश पदानुक्रमित रूप से populating।
मैं एक 'कर्सर' दृष्टिकोण के मामले में सोच रहा था (और File::Spec
इस समय का उपयोग कर):
use File::Spec;
my $data;
my $cursor = \$data;
foreach my $element (File::Spec -> splitdir ($File::Find::dir)) {
$cursor -> {size} += $blocks * $block_size;
$cursor = $cursor -> {$element}
}
हालांकि ... कि काफी डेटा संरचना मैं के लिए, कम से कम नहीं है क्योंकि देख रहा हूँ बनाने नहीं कर रहा है हमें मूल रूप से प्रक्रिया के 'रोलिंग अप' हिस्से को करने के लिए हैश कुंजी द्वारा खोजना है।
क्या इसे पूरा करने का एक बेहतर तरीका है?
संपादित करें - क्या मैं पहले से ही है और पूरी उदाहरण:
#!/usr/bin/env perl
use strict;
use warnings;
use File::Find;
use Data::Dumper;
my $block_size = 1024;
sub collate_sizes {
my ($results_ref, $starting_path) = @_;
$starting_path =~ s,/\w+$,/,;
if (-f $File::Find::name) {
print "$File::Find::name isafile\n";
my ($dev, $ino, $mode, $nlink, $uid,
$gid, $rdev, $size, $atime, $mtime,
$ctime, $blksize, $blocks
) = stat($File::Find::name);
my $dir_tree = $File::Find::dir;
$dir_tree =~ s|^$starting_path||g;
while ($dir_tree) {
print "Updating $dir_tree\n";
$$results_ref{$dir_tree} += $blocks * $block_size;
my @path_arr = split("/", $dir_tree);
pop(@path_arr);
$dir_tree = join("/", @path_arr);
}
}
}
my @users = qw (user1 user2);
foreach my $user (@users) {
my $path = "/home/$user";
print $path;
my %results;
File::Find::find(
{ wanted => sub { \&collate_sizes(\%results, $path) },
no_chdir => 1
},
$path
);
print Dumper \%results;
#would print this to a file in the homedir - to STDOUT for convenience
foreach my $key (sort { $results{$b} <=> $results{$a} } keys %results) {
print "$key => $results{$key}\n";
}
}
और हाँ - मुझे पता है यह पोर्टेबल नहीं है, और कुछ हद तक एक बुरा काम करता है। मैं जो कर रहा हूं उसका हिस्सा उस पर सुधार करने की कोशिश कर रहा है। (लेकिन वर्तमान में यह यूनिक्स आधारित होमडियर संरचना है, तो यह ठीक है)।
आप एक पूरा उदाहरण है कि मैं lazily कॉपी कर सकते हैं/पेस्ट कृपया जोड़ सकते हैं? – simbabque
ठीक है, मेरे साथ भालू। मुझे अपनी स्क्रिप्ट को थोड़ा आकार देने के लिए ट्रिम करना होगा। – Sobrique
ठीक है। एक न्यूनतम उदाहरण जोड़ा गया। (यह बहुत सारे जंक को छोड़ देता है, जैसे यूनिट स्वरूपण और विभिन्न सारांश आउटपुट)। – Sobrique