Linux Command to Find Files/Directories Writable by Specific User Under Subdirectory Tree


3 views

When managing Linux systems, administrators often need to identify files accessible to specific users. The core challenge involves:

  • Evaluating all permission combinations (user/group/other)
  • Accounting for both explicit and inherited permissions
  • Handling special cases like sticky bits and ACLs

Here's the most efficient one-liner to locate writable items for user username under /path/to/directory:

find /path/to/directory -exec \
    sh -c 'test -w "$1" -o \
    $(stat -c "%U" "$1") = "username" -o \
    $(stat -c "%G" "$1") = "$(id -gn username)"' \
    sh {} \; -print

The command works by:

  1. Using find to traverse the directory tree
  2. Checking three possible write conditions via test -w and stat:
    • Direct write permission via -w flag
    • Ownership match (%U)
    • Group membership (%G compared with user's primary group)

For more complex scenarios:

1. Check non-writable files

find /path -exec \
    sh -c '! test -w "$1" && \
    [ "$(stat -c "%U" "$1")" != "username" ] && \
    [ "$(stat -c "%G" "$1")" != "$(id -gn username)" ]' \
    sh {} \; -print

2. Include ACL permissions

find /path -exec \
    sh -c 'getfacl "$1" | grep -q "user:username:rw"' \
    sh {} \; -print

For large directory trees, consider these optimizations:

  • Add -xdev to prevent crossing filesystem boundaries
  • Use -mount instead of -xdev for broader compatibility
  • Limit depth with -maxdepth where appropriate

Finding web directory files writable by www-data:

find /var/www -exec \
    sh -c 'test -w "$1" || \
    [ "$(stat -c "%U" "$1")" = "www-data" ] || \
    [ "$(stat -c "%G" "$1")" = "$(id -gn www-data)" ]' \
    sh {} \; -print -ls

The -ls flag provides detailed permission output for verification.


When managing Linux systems, a common administrative task is identifying filesystem objects accessible to specific users. The complexity arises because Linux permissions involve multiple layers:

  • Direct user ownership (user is owner and has write bit)
  • Group membership (user in group with write permission)
  • World writable (others permission)
  • Special cases (ACLs, capabilities, etc.)

Here's the most precise one-liner to solve this:

find /target/directory -type f -exec bash -c 'sudo -u target_user [ -w "$0" ] && echo "$0"' {} \;

For directories:

find /target/directory -type d -exec bash -c 'sudo -u target_user [ -w "$0" ] && echo "$0"' {} \;

For cases where sudo isn't available, we can analyze permissions directly:

find /target/directory $-perm -u=w -user target_user$ -o \
\( -perm -g=w -group $(id -gn target_user) \) -o \
$-perm -o=w$ -ls

Let's say we need to check which files user "deploy" can modify in /var/www:

#!/bin/bash
TARGET_USER="deploy"
SEARCH_DIR="/var/www"

echo "[+] Checking writable files for $TARGET_USER"
find "$SEARCH_DIR" -type f -exec bash -c \
'if sudo -u '"$TARGET_USER"' [ -w "$0" ]; then 
    ls -la "$0"; 
fi' {} \;

For comprehensive checks including ACLs:

getfacl -R /target/directory | grep -E "user:${TARGET_USER}:..w|group:.*:..w"

The sudo-based method is accurate but slow for large directories. For faster results:

find /target/directory -printf "%u:%g:%m %p\n" | awk -F: -v user="$TARGET_USER" \
'$1 == user && ($3 ~ /[2-7][0-7][2-7]/) || \
$2 == "'"$(id -gn "$TARGET_USER")"'" && ($3 ~ /[0-7][2-7][0-7]/) || \
$3 ~ /[0-7][0-7][2-7]/ {print $0}'