I need to hide all permission denied messages from:
find . > files_and_folders
I am experimenting when such message arises. I need to gather all folders and files, to which it does not arise.
Is it possible to direct the permission levels to the files_and_folders
file?
How can I hide the errors at the same time?
This question is related to
bash
error-handling
find
file-permissions
None of the above answers worked for me. Whatever I find on Internet focuses on: hide errors. None properly handles the process return-code / exit-code. I use command find within bash scripts to locate some directories and then inspect their content. I evaluate command find success using the exit-code: a value zero works, otherwise fails.
The answer provided above by Michael Brux works sometimes. But I have one scenario in which it fails! I discovered the problem and fixed it myself. I need to prune files when:
it is a directory AND has no read access AND/OR has no execute access
See the key issue here is: AND/OR. One good suggested condition sequence I read is:
-type d ! -readable ! -executable -prune
This does not work always. This means a prune is triggered when a match is:
it is directory AND no read access AND no execute access
This sequence of expressions fails when read access is granted but no execute access is.
After some testing I realized about that and changed my shell script solution to:
nice find /home*/ -maxdepth 5 -follow \
\( -type d -a ! \( -readable -a -executable \) \) -prune \
-o \
\( -type d -a -readable -a -executable -a -name "${m_find_name}" \) -print
The key here is to place the "not true" for a combined expression:
has read access AND has execute access
Otherwise it has not full access, which means: prune it. This proved to work for me in one scenario which previous suggested solutions failed.
I provide below technical details for questions in the comments section. I apologize if details are excessive.
You can use the grep -v invert-match
-v, --invert-match select non-matching lines
like this:
find . > files_and_folders
cat files_and_folders | grep -v "permission denied" > files_and_folders
Should to the magic
To avoid just the permission denied warnings, tell find to ignore the unreadable files by pruning them from the search. Add an expression as an OR to your find, such as
find / \! -readable -prune -o -name '*.jbd' -ls
This mostly says to (match an unreadable file and prune it from the list) OR (match a name like *.jbd and display it [with ls]). (Remember that by default the expressions are AND'd together unless you use -or.) You need the -ls in the second expression or else find may add a default action to show either match, which will also show you all the unreadable files.
But if you're looking for real files on your system, there is usually no reason to look in /dev, which has many many files, so you should add an expression that excludes that directory, like:
find / -mount \! -readable -prune -o -path /dev -prune -o -name '*.jbd' -ls
So (match unreadable file and prune from list) OR (match path /dev and prune from list) OR (match file like *.jbd and display it).
If you want to start search from root "/" , you will probably see output somethings like:
find: /./proc/1731/fdinfo: Permission denied
find: /./proc/2032/task/2032/fd: Permission denied
It's because of permission. To solve this:
You can use sudo command:
sudo find /. -name 'toBeSearched.file'
It asks super user's password, when enter the password you will see result what you really want. If you don't have permission to use sudo command which means you don't have super user's password, first ask system admin to add you to the sudoers file.
You can use redirect the Standard Error Output from (Generally Display/Screen) to some file and avoid seeing the error messages on the screen! redirect to a special file /dev/null :
find /. -name 'toBeSearched.file' 2>/dev/null
You can use redirect the Standard Error Output from (Generally Display/Screen) to Standard output (Generally Display/Screen), then pipe with grep command with -v "invert" parameter to not to see the output lines which has 'Permission denied' word pairs:
find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
Use:
find . 2>/dev/null > files_and_folders
This hides not just the Permission denied
errors, of course, but all error messages.
If you really want to keep other possible errors, such as too many hops on a symlink, but not the permission denied ones, then you'd probably have to take a flying guess that you don't have many files called 'permission denied' and try:
find . 2>&1 | grep -v 'Permission denied' > files_and_folders
If you strictly want to filter just standard error, you can use the more elaborate construction:
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2
The I/O redirection on the find
command is: 2>&1 > files_and_folders |
.
The pipe redirects standard output to the grep
command and is applied first. The 2>&1
sends standard error to the same place as standard output (the pipe). The > files_and_folders
sends standard output (but not standard error) to a file. The net result is that messages written to standard error are sent down the pipe and the regular output of find
is written to the file. The grep
filters the standard output (you can decide how selective you want it to be, and may have to change the spelling depending on locale and O/S) and the final >&2
means that the surviving error messages (written to standard output) go to standard error once more. The final redirection could be regarded as optional at the terminal, but would be a very good idea to use it in a script so that error messages appear on standard error.
There are endless variations on this theme, depending on what you want to do. This will work on any variant of Unix with any Bourne shell derivative (Bash, Korn, …) and any POSIX-compliant version of find
.
If you wish to adapt to the specific version of find
you have on your system, there may be alternative options available. GNU find
in particular has a myriad options not available in other versions — see the currently accepted answer for one such set of options.
If you are using CSH or TCSH, here is a solution:
( find . > files_and_folders ) >& /dev/null
If you want output to the terminal:
( find . > /dev/tty ) >& /dev/null
However, as the "csh-whynot" FAQ describes, you should not use CSH.
Those errors are printed out to the standard error output (fd 2). To filter them out, simply redirect all errors to /dev/null:
find . 2>/dev/null > some_file
or first join stderr and stdout and then grep out those specific errors:
find . 2>&1 | grep -v 'Permission denied' > some_file
use
sudo find / -name file.txt
It's stupid (because you elevate the search) and nonsecure, but far shorter to write.
Use:
find . ! -readable -prune -o -print
or more generally
find <paths> ! -readable -prune -o <other conditions like -name> -print
Works with: find (GNU findutils) 4.4.2. Background:
-readable
test matches readable files. The !
operator returns true, when test is false. And ! -readable
matches not readable directories (&files).-prune
action does not descend into directory.! -readable -prune
can be translated to: if directory is not readable, do not descend into it.-readable
test takes into account access control lists and other permissions artefacts which the -perm
test ignores.See also find
(1) manpage for many more details.
Pipe stderr
to /dev/null
by using 2>/dev/null
find . -name '...' 2>/dev/null
While above approaches do not address the case for Mac OS X because Mac Os X does not support -readable
switch this is how you can avoid 'Permission denied' errors in your output. This might help someone.
find / -type f -name "your_pattern" 2>/dev/null
.
If you're using some other command with find
, for example, to find the size of files of certain pattern in a directory 2>/dev/null
would still work as shown below.
find . -type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$
.
This will return the total size of the files of a given pattern. Note the 2>/dev/null
at the end of find command.
I had to use:
find / -name expect 2>/dev/null
specifying the name of what I wanted to find and then telling it to redirect all errors to /dev/null
expect being the location of the expect program I was searching for.
-=For MacOS=-
Make a new command using alias: just add in ~/.bash_profile line:
alias search='find / -name $file 2>/dev/null'
and in new Terminal window you can call it:
$ file=<filename or mask>; search
for example:
$ file=etc; search
You can also use the -perm
and -prune
predicates to avoid descending into unreadable directories (see also How do I remove "permission denied" printout statements from the find program? - Unix & Linux Stack Exchange):
find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders
find . > files_and_folders 2>&-
2>&-
closes (-
) the standard error file descriptor (2
) so all error messages are silenced.
1
if any 'Permission denied
' errors would otherwise be printedfind
:find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_folders
Pass extra options to find
that -prune
(prevent descending into) but still -print
any directory (-type
d
) that does not (\!
) have both -readable
and -executable
permissions, or (-o
) -print
any other file.
-readable
and -executable
options are GNU extensions, not part of the POSIX standardPermission denied
' on abnormal/corrupt files (e.g., see bug report affecting container-mounted filesystems using lxcfs
< v2.0.5)find
(GNU, OSX/BSD, etc){ LC_ALL=C find . 3>&2 2>&1 1>&3 > files_and_folders | grep -v 'Permission denied'; [ $? = 1 ]; } 3>&2 2>&1
Use a pipeline to pass the standard error stream to grep
, removing all lines containing the 'Permission denied'
string.
LC_ALL=C
sets the POSIX locale using an environment variable, 3>&2 2>&1 1>&3
and 3>&2 2>&1
duplicate file descriptors to pipe the standard-error stream to grep
, and [ $? = 1 ]
uses []
to invert the error code returned by grep
to approximate the original behavior of find
.
'Permission denied'
errors due to output redirection (e.g., if the files_and_folders
file itself is not writable)Redirect standard error. For instance, if you're using bash on a unix machine, you can redirect standard error to /dev/null like this:
find . 2>/dev/null >files_and_folders
Source: Stackoverflow.com