LinuxTutorials

How to mass change file ownerships, even symbolic links

A situation may happen, where one must quickly change the ownership of all files matching a certain name, a certain modification date or are within a certain path.

Important note: An ownership change can only be performed with root privileges.

Recursive ownership change

When all content of a certain path (here /var/www/example.com) needs to be changed, a recursive chown is the fastest way to achieve this goal:

root@linux:~# chown -R geek:geek /var/www/example.com/

Ownership change on certain files only

It's obvious to most Linux users to use the find command to obtain a list of the target files. In the following example, all files are listed which are not owned by the user geek within the current path:

root@linux:/var/www/example.com/current# find . ! -user geek
./generated/code/Klarna
./generated/code/Klarna/Core
./generated/code/Klarna/Core/Api
./generated/code/Klarna/Core/Api/VersionInterfaceFactory.php
./generated/code/Klarna/Core/Helper
./generated/code/Klarna/Core/Helper/KlarnaConfig
./generated/code/Klarna/Core/Helper/KlarnaConfig/Proxy.php
[...]

To change the owner to all these files to geek, use the -exec parameter followed by the command line command to change the ownership (chown). The {} + is a placeholder for the file path which was found by find:

root@linux:/var/www/example.com/current# find . ! -user geek -exec chown geek:geek {} +

The symlink exception

However there is one exception where the ownerships are not changed: symbolic links. If you launch the first find command again (to simply list the results), you might be surprised to still find some files with unchanged ownerships:

root@linux:/var/www/example.com/current# find . ! -user geek 
./pub/static/frontend/Alva/Example/fr_FR/images/buton__subscr.png
./pub/static/frontend/Alva/Example/fr_FR/images/t3.png
./pub/static/frontend/Alva/Example/fr_FR/images/stripe-red.png
./pub/static/frontend/Alva/Example/fr_FR/images/t4.png
./pub/static/frontend/Alva/Example/fr_FR/images/right-arrow.png
./pub/static/frontend/Alva/Example/fr_FR/images/t2.png
[...]

Taking a closer look at these paths, reveal they are all symlinks. This can be verified with a simple ls or append -type l to the find command:

root@linux:/var/www/example.com/current# ls -la ./pub/static/frontend/Alva/Example/fr_FR/Magento_Ui/templates/form/field.html
lrwxrwxrwx 1 www-data www-data 109 Jan 29 09:56 ./pub/static/frontend/Alva/Example/fr_FR/Magento_Ui/templates/form/field.html -> /var/www/example.com/releases/origin/vendor/magento/module-ui/view/frontend/web/templates/form/field.html

root@linux:/var/www/example.com/current# find . ! -user geek -type l
./pub/static/frontend/Alva/Example/fr_FR/images/buton__subscr.png
./pub/static/frontend/Alva/Example/fr_FR/images/t3.png
./pub/static/frontend/Alva/Example/fr_FR/images/stripe-red.png
./pub/static/frontend/Alva/Example/fr_FR/images/t4.png
./pub/static/frontend/Alva/Example/fr_FR/images/right-arrow.png
./pub/static/frontend/Alva/Example/fr_FR/images/t2.png
[...]

The reason is that symbolic links require an additional parameter (-h) to chown, otherwise the ownership of symlinks will not change. From the manual page:

   -h, --no-dereference
          affect symbolic links instead of any referenced file (useful only on systems that can change the ownership of a symlink)

In this case, use the find command from above again, but this time append the chown command with the -h parameter:

root@linux:/var/www/example.com/current# find . ! -user geek -type l -exec chown -h geek:geek {} +

No surprise this time: All the files are now owned by geek:

root@linux:/var/www/example.com/current# find . ! -user geek; echo "done"
done
root@linux:/var/www/example.com/current# 

Claudio Kuenzler
Claudio has been writing way over 1000 articles on his own blog since 2008 already. He is fascinated by technology, especially Open Source Software. As a Senior Systems Engineer he has seen and solved a lot of problems - and writes about them.

Leave a reply

Your email address will not be published. Required fields are marked *

More in:Linux