I'm trying to find some large files in a specific location:
This command works and returns some results:
admin@tyrell:~$ sudo find /nfshome/*/.local/ -type f -size +1G -exec ls -lh {} \;
-rw-r--r-- 1 9917183 students 5.2G Jun 5 2017 /nfshome/9917183/.local/share/Trash/files/result_25.zip
-rw-r--r-- 1 9918178 students 4.0G Sep 6 2018 /nfshome/9918178/.local/share/unity3d/Asset Store-5.x/Unity Technologies/Unity EssentialsSample Projects/3D Game Kit.unitypackage
-rw-r--r-- 1 9919185 students 2.1G Mar 6 2018 /nfshome/9919185/.local/share/Trash/files/agggg.avi
-rw-r--r-- 1 9919382 students 1.7G Jan 17 2017 /nfshome/9919382/.local/share/Trash/files/MageWar.avi
-rw-r--r-- 1 9921459 students 1.8G Apr 12 11:58 /nfshome/9921459/.local/share/Trash/files/takeout-20190412T182950Z-001(1).zip
-rw-r--r-- 1 9921459 students 1.8G Apr 12 11:58 /nfshome/9921459/.local/share/Trash/files/takeout-20190412T182950Z-001.zip
-rw-r--r-- 1 9921459 students 1.4G Apr 12 11:56 /nfshome/9921459/.local/share/Trash/files/takeout-20190412T182950Z-003.zip
-rw-r--r-- 1 9921459 students 1.4G Apr 12 11:58 /nfshome/9921459/.local/share/Trash/files/takeout-20190412T182950Z-003(1).zip
but if I try to narrow the search by adding one more subdirectory, share/
, I get nothing, where I would expect to get the exact same result, because everything above is in share/
:
admin@tyrell:~$ sudo find /nfshome/*/.local/share/ -type f -size +1G -exec ls -lh {} \;
admin@tyrell:~$
Why doesn't find return the same result as the first command?
Best Answer
The reason this fails is to do with permissions and the wildcard
*
character. We can reproduce this on a local file-system like this:Set up the scenario, a directory tree under
/tmp/top
:Notice that we have no permission as an ordinary user to go below
/tmp/top/*/dir
:Try descending with root privileges from a directory that we cannot reach as an ordinary user:
Remember the evaluation of shell wildcards happens before the command is executed. So what is happening here is that the path containing the wildcard
*
is expanded. Your ordinary user account cannot verify the existence ofsub
, and so the entire path cannot be verified. The wildcard remains as an asterisk (the default behaviour when a match fails) and the root privilegedfind
is given the literal path/tmp/top/*/dir/sub
to descend. This path does not exist, hence the error.Try descending with root privileges from a directory that we can reach as an ordinary user:
What happens here is similar, but with more useful consequences. The path
/tmp/top/*/dir
can be evaluated completely as your ordinary user, resulting in two paths/tmp/top/a/dir
and/tmp/top/b/dir
. These are passed to the root privilegedfind
, and it can subsequently descend these - through the root-only subdirectory - and list the files it discovers.In your situation, it is highly likely that the
.local
directories in your wildcarded path cannot be accessed without root privileges, but the higher level directories are quite accessible. While you specify a path that can be evaluated as your ordinary user account, thefind
can proceed with the expanded set of paths. As soon as you specify a path that cannot be evaluated in the context of your ordinary user account, the expansion fails andfind
is passed a path that contains a literal*
character. This of course fails to match and thefind
fails.To resolve the issue you simply need to defer the evaluation of the path until your command is running as root: