#!/usr/bin/env perl use strict; use warnings; use autodie; use constant BASE_DIR => '/home/ken/tmp/pm_11143050'; use constant { LEN_BASE_DIR => length BASE_DIR, FS_DIR => BASE_DIR . '/fs', }; use Cwd 'abs_path'; use Data::Dump; my %fs_map; walk_fs(FS_DIR, \%fs_map); dd \%fs_map; sub walk_fs { my ($path, $fs_map) = @_; opendir(my $dh, $path); while (readdir $dh) { next if /^\.{1,2}$/; my $entry = "$path/$_"; my $fs_path = fs_path($entry); if (-f $entry) { $fs_map->{$fs_path} = [file => []]; } elsif (-l $entry) { $fs_map->{$fs_path} = [link => [canon_path($entry)]]; } elsif (-d $entry) { if (exists $fs_map->{fs_path($path)}) { push @{$fs_map->{fs_path($path)}[1]}, canon_path($entry); } $fs_map->{$fs_path} = [dir => []]; walk_fs($entry, $fs_map); } else { warn "IGNORED '$entry': not a plain file, link or directory.\n"; } } closedir $dh; return; } sub fs_path { return substr $_[0], LEN_BASE_DIR; } sub canon_path { return substr abs_path($_[0]), LEN_BASE_DIR; } #### ken@titan ~/tmp/pm_11143050 $ ls -lR fs fs: total 0 drwxr-xr-x+ 1 ken None 0 Apr 19 03:49 a drwxr-xr-x+ 1 ken None 0 Apr 19 02:46 t fs/a: total 1 prw-rw-rw- 1 ken None 0 Apr 19 03:49 a_named_pipe drwxr-xr-x+ 1 ken None 0 Apr 19 02:46 b -rw-r--r-- 1 ken None 0 Apr 19 02:36 d lrwxrwxrwx 1 ken None 5 Apr 19 02:42 r -> b/c/z drwxr-xr-x+ 1 ken None 0 Apr 19 02:46 u lrwxrwxrwx 1 ken None 8 Apr 19 02:35 x -> ../a/b/c fs/a/b: total 0 drwxr-xr-x+ 1 ken None 0 Apr 19 02:46 c -rw-r--r-- 1 ken None 0 Apr 19 02:37 e lrwxrwxrwx 1 ken None 1 Apr 19 02:40 q -> y drwxr-xr-x+ 1 ken None 0 Apr 19 02:46 v lrwxrwxrwx 1 ken None 1 Apr 19 02:37 y -> . fs/a/b/c: total 0 -rw-r--r-- 1 ken None 0 Apr 19 02:38 f lrwxrwxrwx 1 ken None 7 Apr 19 02:40 p -> ../../x drwxr-xr-x+ 1 ken None 0 Apr 19 02:46 w lrwxrwxrwx 1 ken None 6 Apr 19 02:38 z -> ../../ fs/a/b/c/w: total 0 fs/a/b/v: total 0 fs/a/u: total 0 fs/t: total 0 #### ken@titan ~/tmp/pm_11143050 $ ./mapfs.pl IGNORED '/home/ken/tmp/pm_11143050/fs/a/a_named_pipe': not a plain file, link or directory. { "/fs/a" => ["dir", ["/fs/a/b", "/fs/a/u"]], "/fs/a/b" => ["dir", ["/fs/a/b/c", "/fs/a/b/v"]], "/fs/a/b/c" => ["dir", ["/fs/a/b/c/w"]], "/fs/a/b/c/f" => ["file", []], "/fs/a/b/c/p" => ["link", ["/fs/a/b/c"]], "/fs/a/b/c/w" => ["dir", []], "/fs/a/b/c/z" => ["link", ["/fs/a"]], "/fs/a/b/e" => ["file", []], "/fs/a/b/q" => ["link", ["/fs/a/b"]], "/fs/a/b/v" => ["dir", []], "/fs/a/b/y" => ["link", ["/fs/a/b"]], "/fs/a/d" => ["file", []], "/fs/a/r" => ["link", ["/fs/a"]], "/fs/a/u" => ["dir", []], "/fs/a/x" => ["link", ["/fs/a/b/c"]], "/fs/t" => ["dir", []], }