17

Under Linux, how can I find all the files and directories that are writable (or, actually, not writable) by a particular user?

Edit: To clarify, I meant under a particular subdir, not systemwide. And yes, that means all the permutations and combinations of user, group and world writability that would allow that user to write. I know what the question entails semantically, I was hoping for a one- or few-liner to execute to get a list of these files.

1
  • Okay, thanks to everyone for the answers. I already found the "find" solution via google, but was wondering if there were some way to generically apply it to a given user. Looks like there is no other way than to su as the user, then run the find command -- unless anyone else chimes in? I will accept Ophidian's answer some time tomorrow barring any better responses.
    – Pistos
    Jun 2, 2009 at 2:51

8 Answers 8

26

Use the 'find' command if you have findutils version 4.3.0 or greater installed:

For all files under the current directory that are writable by the current user:

find . -writable

For all files under the current directory that are not writable by the current user:

find . ! -writable

According to the man page:

This test makes use of the access(2) system call, and so can be fooled by NFS servers which do UID mapping (or root-squashing), since many systems implement access(2) in the client’s kernel and so cannot make use of the UID mapping information held on the server.

3
  • 4
    Just thought I'd mention for further edification: I actually had to do this with a user who didn't have a login shell ( /sbin/nologin ). To do that, I used sudo, like this: sudo -u nobody find . ! -writable
    – Pistos
    Jun 7, 2009 at 17:09
  • 3
    This doesn't answer the question and therefore shouldn't be the accepted answer. The question was about "a particular user", not about the "current user".
    – jlh
    Feb 7, 2017 at 10:20
  • and to hide the permission denied errors add 2>&1 | grep -v "Permission denied" to be find . -writable 2>&1 | grep -v "Permission denied"
    – iolsmit
    Aug 24, 2017 at 17:56
3

You can create a Perl script (writable.pl) like this:

#!/usr/bin/perl

use strict;

sub recurse {
  my $path = shift;
  my @files = glob "$path/{*,.*}";
  for my $file (@files) {
    if (-d $file) {
      if ($file !~ /\/\.$/ && $file !~ /\/\.\.$/) {
        recurse($file);
      }
    } else {
      print "$file\n" if -w $file;
    }
  }
}

print "Writable files for " . getlogin() . "\n";
recurse($ARGV[0]);

and then use this script, as root, as follows:

su USERNAME -c "./writable.pl DIRECTORY"

filling in USERNAME and DIRECTORY as appropriate.

1
  • Excellent. Thank you. The $ARGV[0] is taken as empty in the bash shell on CentOS 6.2. Not sure why. I modified the script to read from a file.
    – doon
    Apr 20, 2013 at 12:42
3

This command should find all writable directories, you can change the permissions as you see fit:

find / -type d \( -perm -g+w -or -perm -o+w \) -exec ls -adl {} \;
0
2

I'll use the gnu find syntax for the -perm flag in this example:

Basically -- if you throw out wacky extensions like ACLs, you've got 3 chocies - owner, group, and "other" write access. Sounds like a job for a loop.

There is plenty of room to optimize this but I'll leave that to someone else... Also, I never can remember all the details of find and crossing filesystems and that sort of nonsense. Also, make sure the output of groups is the same as on my test linux system

$ groups snoopy
snoopy : snoopy doghouse linus admin wwI woodstock
$

This is a rough example of how you'd find files writable by a user. This will when run as any user, but if you run it as a non-uid0 user you'll only find things that are in directories that the user running the script has both read and execute permissions to.

#!/bin/sh

user=snoopy

directory=/

# first files owned by the user and writable
find "$directory" -follow -user "$user" -perm /u+w 2> /dev/null


# now for files that are group writable with the user in that group
for groups in $(groups snoopy 2> /dev/null | cut -f2 -d:)
do
  find "$directory" -follow -group "$user" -perm /g+w 2> /dev/null
done

# now for everything else
find "$directory" -follow -perm /o+w 2> /dev/null
1

For Eddie's answer if you throw in:

my $path = quotemeta shift;

Then it will traverse directories with spaces in their name as well.

0

Are you sure that is really the question that you want to be asking?

To say "I want to see all files that X account can write to" means every file owned by them with u+w, every file owned by any group they belong to that's set g+w, and every file world writable (o+w).

Not writable would be even harder. You'd be better off to make a list of every file, then exclude those that they can write to.

2
  • 3
    Of course it is even more complicated if the system has ACLs enabled.
    – Zoredache
    Jun 2, 2009 at 0:08
  • 2
    Not counting chattr +i files Jun 2, 2009 at 0:12
0

I'm not sure if this is the best way, but should do what you ask:

for file in *
do 
    if [ -w $file ] ; then 
        echo $file
    fi
done

key is of course in -w switch, which can also be negated

EDIT: Thinking more about this, this script prints what is writable by current user, it obviously wouldn't work for some given user.

3
  • Of course, you have to run this script as that user.
    – Eddie
    Jun 2, 2009 at 0:54
  • yeah, figured... Jun 2, 2009 at 0:57
  • how would you write this in perl?
    – ealeon
    Jan 21, 2018 at 19:45
0

Linux test -w /foldername/filename can check whether current user has write access to file or not. The process returns 0 in case has, or non-zero if doesn’t.

As admin or root you can login on behalf of a user, and combine test command with find command, so list of command will look like following:

sudo su username
find /folder/subfolder -exec test -w {} \; -exec echo {} \; 2>/dev/null

It quite bit slow to run every file through test -w however will check if it is writeable for sure

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .