#!/usr/bin/perl #written by Nick on 2006-08-10 #nstat stands for Nick's Stat #nstat prints out nicely formatted file stats for a file #To install: cp nstat /usr/bin ; chmod 755 /usr/bin/nstat #This script is most useful for finding hard links to files/directories #This script is also nice for viewing file times in date formats my ($file,$scanwhole) = @ARGV; unless($file) { die "USAGE: nstat filename [1 for scan entire current filesystem for hard links]\n\n", "Example: nstat testlink 1 #to scan entire current filesystem for hard link\n", "Example: nstat test.txt #just to view stats on file test.txt\n"; } my %descriptions = ( 'file','filename', 'dev','device number of filesystem', 'ino','inode number', 'mode','file mode (type and permissions)', 'nlink','number of (hard) links to the file', 'uid','numeric user ID of file\'s owner', 'gid','numeric group ID of file\'s owner', 'rdev','device identifier (special files only)', 'size','total size of file, in bytes', 'atime','last access time, seconds since epoch', 'mtime','last modify time, seconds since epoch', 'ctime','inode change time, seconds since epoch', 'blksize','preferred block size for FS I/O', 'blocks','actual number of blocks allocated' ); my @descr = qw(dev ino mode nlink uid gid rdev size atime mtime ctime blksize blocks); print "Stats for file $file\n"; use File::stat qw(:FIELDS); my $st = stat($file) or die "No such file '$file': $!\n"; my ($d,$extra); format STDOUT = @<<<<<< @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<< $one, $two, $three, $extra . $one = ''; $two = 'file name'; $three = $ARGV[0]; write; my $fileBin = `which file`; if($fileBin) { $one = ''; $two = 'file type'; my @info = split(':', `file $ARGV[0]`); my $finfo = $info[1]; #strip leading and trailing whitespace $finfo =~ s/\s+$//; $finfo =~ s/^\s+//; #strip leading and trailing whitespace $finfo =~ s/\s+$//; $finfo =~ s/^\s+//; $three = $finfo; } else { $one = ''; $two = 'file type'; $three = 'N/A'; } write; $one = ''; $two = ''; $three = ''; write; foreach $d (@descr) { if($d =~ /time/) { my @ds = localtime($st->$d); # 0 1 2 3 4 5 6 7 8 #($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = # localtime(time); my $y = $ds[5]+1900; my $m = $ds[4]+1; my $d = $ds[3]; my $H = $ds[2]; my $M = $ds[1]; $m = '0'.$m if $m < 10; $d = '0'.$d if $d < 10; $H = '0'.$H if $H < 10; $M = '0'.$M if $M < 10; $extra = "$y-$m-$d $H:$M"; } elsif($d eq 'size') { my $siM = sprintf("%.2f", ($st->$d/1024/1024)); my $siG = sprintf("%.2f", ($st->$d/1024/1024/1024)); $extra = "~$siM Mb, ~$siG Gb"; } elsif($d eq 'nlink') { if($st->$d > 1) { my $ol = $st->$d; $ol--; $one = $d; $two = $st->$d; $three = $descriptions{$d}; $extra = "$ol other links to this inode"; write; my $find = `which find`; if($find) { $one = ''; $two = ''; my $dir = '.'; if($scanwhole == 1) { $dir = `df -l . | tail -1 | awk '{print $6}'`; $three = "Other linked files found filesystem '$dir'"; } else { $three = "Other linked files found in '.'"; } $extra = ''; write; my $i = 'ino'; my $fcmd = "find $dir -inum ".$st->$i." ! -name '$ARGV[0]'\n"; my @files = `$fcmd`; my $fc = 0; foreach my $f (@files) { $fc++; $one = ''; $two = "# $fc"; $three = $f; $extra = ''; write; } } else { $one = ''; $two = 'ERROR'; $three = 'cannot find other linked files'; $extra = "'find' not found"; write; } } } elsif($d eq 'gid') { my ($gname, $gpass, $gid, $gmembers) = getgrgid($st->$d); if($gname) { $extra = "grp: $gname, mbrs: '$gmembers'"; } else { $extra = "Non-existant group $st->$d"; } } elsif($d eq 'uid') { my @udata = getpwuid($st->$d); if($udata[0]) { $extra = "usr: $udata[0] ($udata[6])"; } else { $extra = "Non-existant user $st->$d"; } } elsif($d eq 'mode') { $extra = sprintf("%04o", $st->$d & 07777); } else { $extra = 'N/A'; } if($d ne 'nlink') { $one = $d; $two = $st->$d; $three = $descriptions{$d}; write; } }