2

I would like to view the unique owners of all the files and directories underneath a certain directory.

I have tried:

ls -ltR <dir-path> | grep -P '^[d|\-]' | awk '{print $3}' | sort | uniq

Which commits the cardinal sin of trying to parse ls output, but works -- until I try it on a directory with an immense amount of files within a complex directory structure where it bogs down and hangs.

While I could work around and simply do the command at lower levels and work up piece by piece, I was wondering if there is a more efficient way to do this in one fell swoop?

3

Here's a slightly shorter version that uses find:

find <path> -printf "%u\n" | sort -u

Depending on the complexity of the directory structure, this may or may not be more efficient.

  • 1
    In this case (i.e. assuming number of files is large, number of users is small), gawk '1{u[$0]=1;} END{ for (x in u){print x;}}' might be better than sort -u since it doesn't store one line per file. – Ulrich Schwarz May 6 '15 at 16:40
  • Good point. I think uniq -u does essentially the same thing, I've updated my response. – kartik_subbarao May 6 '15 at 17:33
  • @don_crissti You're right -- sloppy reading of the man page on my part. I've changed my answer back to sort -u. Ulrich's answer will be more efficient. – kartik_subbarao May 6 '15 at 21:31
2

For this sort of task, I like to break out the perl. There's a module called File::Find which is core, that is quite good for this:

#!/usr/bin/perl
use strict;
use warnings;

use File::Find;

my %found;

sub collate_users {
    next if -d;
    my ($dev,  $ino,   $mode,  $nlink, $uid,     $gid, $rdev,
        $size, $atime, $mtime, $ctime, $blksize, $blocks
    ) = stat;

    if ( not $found{$uid} ) {
        print "$uid : ", getpwuid($uid),"\n";
    }
    $found{$uid}++;
}

find( \&collate_users, "/path/to/search", "/another/path/to/search" );

This'll print in 'found order' - you could if you prefer, collate and sort (by count of files if you're so inclined) later:

foreach my $uid ( sort { $found{$a} <=> $found{$b} } keys %found ) {
    print getpwbyuid($uid)," ($uid) has $found{$uid} files\n";
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.