826

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?

Jahid
  • 18,228
  • 8
  • 79
  • 95
Léo Léopold Hertz 준영
  • 119,377
  • 159
  • 417
  • 655

17 Answers17

553

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.

HelloGoodbye
  • 2,752
  • 6
  • 32
  • 43
Jonathan Leffler
  • 666,971
  • 126
  • 813
  • 1,185
  • 9
    If you are like me, notice that lack of space is important! `2>/dev/null`, without space! – Nik Oct 25 '13 at 08:00
  • 20
    The `2>` is a single unit without any spaces; you can have a space between it and the file name. Similarly with other redirections, such as `2>&1` (which redirects standard error to the same place as standard output is going), or `2>&-` which closes standard error, etc. See [Redirections](http://www.gnu.org/software/bash/manual/bash.html#Redirections) for the remaining gory details. (The code above is generic POSIX-like shell, not specific to `bash`.) – Jonathan Leffler Oct 25 '13 at 18:12
  • 3
    I had to use a capital P because that's what my terminal would output:find . 2>&1 | grep -v 'Permission denied' – David Doria May 29 '14 at 20:20
  • 1
    @DavidDoria you can use `grep -i` or (in this case) `grep -vi` to ignore case. – AndriusZ Aug 12 '14 at 13:59
  • 4
    How is this an acceptable solution? 1) You're redirecting ALL errors to dev/null 2) You're filtering an explicit error string!! Depending on these is famously brittle and what if your file was in a directory named 'permission denied'? Oops! – Gunchars Nov 10 '14 at 06:03
  • 2
    @Gunchars: the points you raise are covered in the answer — or the explicit error string is covered by the specification of the question. The first command does send all errors to `/dev/null`; the second does not. And the answer mentions the assumption that you don't have any files called `permission denied`. So, I'm not clear what you're really objecting to. – Jonathan Leffler Nov 10 '14 at 06:20
  • 10
    I'm objecting against grepping error strings to modify program's output. It will work most of the time, but simple isn't the correct solution (find with perms below is). To give you an example why, this will not work on OSX because the error is "Permission denied". Same for any other system where there's even minuscule differences in the error string (internationalization anyone?) – Gunchars Nov 10 '14 at 15:59
  • 1
    To make grep-ing somewhat more robust, better use `LANG=C grep` as, depending on localization, messages will otherwise vary and grep won't match them. Still not as solid as user3701456's answer. – Thomas W Feb 16 '16 at 09:34
  • @ThomasW: Good point, but it is the `find` command (not `grep`) you must prefix with `LANG=C` (or, slightly more robustly, `LC_ALL=C`). – mklement0 Nov 01 '16 at 06:18
295

Use:

find . ! -readable -prune -o -print

or more generally

find <paths> ! -readable -prune -o <other conditions like -name> -print
  • to avoid "Permission denied"
  • AND do NOT suppress (other) error messages
  • AND get exit status 0 ("all files are processed successfully")

Works with: find (GNU findutils) 4.4.2. Background:

  • The -readable test matches readable files. The ! operator returns true, when test is false. And ! -readable matches not readable directories (&files).
  • The -prune action does not descend into directory.
  • ! -readable -prune can be translated to: if directory is not readable, do not descend into it.
  • The -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.

gtgaxiola
  • 8,840
  • 5
  • 41
  • 60
Michael Brux
  • 3,838
  • 1
  • 15
  • 20
  • 1
    How is this better or worser than Jonathan's answer? Do both have the same outputs? – Léo Léopold Hertz 준영 Aug 11 '14 at 05:31
  • 6
    the differences are already mentioned. if you don't understand, then the answers maybe make no difference for you? STDOUT is the same - STDERR is different (you get the other error messages with this answer) - $? is different (is 0 "successful" with this answer, when no other error occurs - is always > 0 "not successfull" when redirecting to dev/null) - maybe someone needs "correct" $? in a script – Michael Brux Aug 11 '14 at 05:51
  • 5
    I think this is the more elegant solution of the thread. I like the successful result $?. – Speredenn Nov 21 '14 at 13:43
  • 6
    @Masi the most obvious flaw is Jonathan's answer(grep -v) will exclude filename which contains 'Permission denied' :) – Fruit Apr 10 '15 at 20:11
  • 66
    I feel it appropriate to add here that if you need to add some other search criteria, that should be done with `-o`: `find . ! -readable -prune -o -name '*.txt'` – tempestadept Apr 30 '15 at 11:08
  • 23
    Note that POSIX `find` does not include `-readable` as an option; neither does the `find` for BSD and hence Mac OS X (I'm not sure about other systems). So, where you have GNU `find` guaranteed, this works great, but it isn't obvious how to adapt this if you can't guarantee that the system has GNU `find` installed. (It'll work fine on Linux; it may or may not work elsewhere.) – Jonathan Leffler Jun 27 '15 at 20:56
  • 6
    `find . ! -readable -prune -o -name '*.txt'` doen't seem to work on Ubuntu 14.04 using find 4.2.2. It seems to ingore the `-name`. For some weird reason I has success with `find . \( ! -readable -prune \) -o -name '*.txt' -print` – con-f-use Jan 15 '16 at 17:10
  • 2
    @con-f-use - I had the same issue, I found I only needed the `-print`, not the complicated brackets. – IBam Mar 03 '16 at 16:43
  • Is there an equivalent to ignore non-existentent paths? E.g., if I have `find path1 path2 path3 -type f`, I don't want find to give an error even if the paths are missing. Otherwise, I have to construct the path list in advance by checking which ones exist and not having any path is not an error condition for me. – haridsv Jun 24 '16 at 06:58
  • 1
    @con-f-use See additional explanation re: brackets and `-print` here: http://stackoverflow.com/questions/1489277/how-to-use-prune-option-of-find-in-sh – DreadPirateShawn Sep 27 '16 at 22:16
  • @haridsv: No: `find` invariably complains about nonexistent _input_ paths. You'll have to use one of the solutions that filter `find`'s stderr output and filter out `No such file or directory` messages. – mklement0 Dec 30 '16 at 14:13
  • @MichaelBrux: A belated ++; the discussion below my answer went on, and the updated version is hopefully more balanced. A readable but non-executable dir. still causing permission-denied errors for its child items is not a bug, after all: since the directory itself is readable, `-prune` doesn't kick in, and accessing the child items then fails (due to lack of executable permissions on the dir). As stated, though, it is an exotic case. – mklement0 Dec 30 '16 at 14:38
  • 1
    Could this be restricted further to prune directories which are not executable in addition to not readable? – Andrew McKinlay Jan 16 '17 at 22:41
  • 1
    @AndrewMcKinlay see https://www.gnu.org/software/findutils/manual/html_mono/find.html#Mode-Bits GNU find supports -executable test – Michael Brux Jan 18 '17 at 10:27
  • 3
    @con-f-use your command worked because you added `-print` to the end. That acted on the matches of `-name '*.txt'.` When you add `-print` to one of the clauses in the `-o` (logical OR), find knows that you only want to print that part. Otherwise, if defaults to printing everything it finds. And the unreadable thing was "found", although not readable. (...as described well in the link that DreadPirateShawn posted, now that I pay attention) – Dan Pritts Mar 29 '17 at 19:05
  • Maybe you want to use `! -readable -prune -false` to suppress unreadable directories (and not only the warning) – Henning Apr 04 '17 at 08:49
  • as a note, doesn't appear to work in a cygwin/msys env – xenoterracide Jan 16 '18 at 11:47
290

Note:
* This answer probably goes deeper than the use case warrants, and find 2>/dev/null may be good enough in many situations. It may still be of interest for a cross-platform perspective and for its discussion of some advanced shell techniques in the interest of finding a solution that is as robust as possible, even though the cases guarded against may be largely hypothetical.
* If your system is configured to show localized error messages, prefix the find calls below with LC_ALL=C (LC_ALL=C find ...) to ensure that English messages are reported, so that grep -v 'Permission denied' works as intended. Invariably, however, any error messages that do get displayed will then be in English as well.

If your shell is bash or zsh, there's a solution that is robust while being reasonably simple, using only POSIX-compliant find features; while bash itself is not part of POSIX, most modern Unix platforms come with it, making this solution widely portable:

find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)

Note: There's a small chance that some of grep's output may arrive after find completes, because the overall command doesn't wait for the command inside >(...) to finish. In bash, you can prevent this by appending | cat to the command.

  • >(...) is a (rarely used) output process substitution that allows redirecting output (in this case, stderr output (2>) to the stdin of the command inside >(...).
    In addition to bash and zsh, ksh supports them as well in principle, but trying to combine them with redirection from stderr, as is done here (2> >(...)), appears to be silently ignored (in ksh 93u+).

    • grep -v 'Permission denied' filters out (-v) all lines (from the find command's stderr stream) that contain the phrase Permission denied and outputs the remaining lines to stderr (>&2).

This approach is:

  • robust: grep is only applied to error messages (and not to a combination of file paths and error messages, potentially leading to false positives), and error messages other than permission-denied ones are passed through, to stderr.

  • side-effect free: find's exit code is preserved: the inability to access at least one of the filesystem items encountered results in exit code 1 (although that won't tell you whether errors other than permission-denied ones occurred (too)).


POSIX-compliant solutions:

Fully POSIX-compliant solutions either have limitations or require additional work.

If find's output is to be captured in a file anyway (or suppressed altogether), then the pipeline-based solution from Jonathan Leffler's answer is simple, robust, and POSIX-compliant:

find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2

Note that the order of the redirections matters: 2>&1 must come first.

Capturing stdout output in a file up front allows 2>&1 to send only error messages through the pipeline, which grep can then unambiguously operate on.

The only downside is that the overall exit code will be the grep command's, not find's, which in this case means: if there are no errors at all or only permission-denied errors, the exit code will be 1 (signaling failure), otherwise (errors other than permission-denied ones) 0 - which is the opposite of the intent.
That said, find's exit code is rarely used anyway, as it often conveys little information beyond fundamental failure such as passing a non-existent path.
However, the specific case of even only some of the input paths being inaccessible due to lack of permissions is reflected in find's exit code (in both GNU and BSD find): if a permissions-denied error occurs for any of the files processed, the exit code is set to 1.

The following variation addresses that:

find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }

Now, the exit code indicates whether any errors other than Permission denied occurred: 1 if so, 0 otherwise.
In other words: the exit code now reflects the true intent of the command: success (0) is reported, if no errors at all or only permission-denied errors occurred.
This is arguably even better than just passing find's exit code through, as in the solution at the top.


gniourf_gniourf in the comments proposes a (still POSIX-compliant) generalization of this solution using sophisticated redirections, which works even with the default behavior of printing the file paths to stdout:

{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1

In short: Custom file descriptor 3 is used to temporarily swap stdout (1) and stderr (2), so that error messages alone can be piped to grep via stdout.

Without these redirections, both data (file paths) and error messages would be piped to grep via stdout, and grep would then not be able to distinguish between error message Permission denied and a (hypothetical) file whose name happens to contain the phrase Permission denied.

As in the first solution, however, the the exit code reported will be grep's, not find's, but the same fix as above can be applied.


Notes on the existing answers:

  • There are several points to note about Michael Brux's answer, find . ! -readable -prune -o -print:

    • It requires GNU find; notably, it won't work on macOS. Of course, if you only ever need the command to work with GNU find, this won't be a problem for you.

    • Some Permission denied errors may still surface: find ! -readable -prune reports such errors for the child items of directories for which the current user does have r permission, but lacks x (executable) permission. The reason is that because the directory itself is readable, -prune is not executed, and the attempt to descend into that directory then triggers the error messages. That said, the typical case is for the r permission to be missing.

    • Note: The following point is a matter of philosophy and/or specific use case, and you may decide it is not relevant to you and that the command fits your needs well, especially if simply printing the paths is all you do:

      • If you conceptualize the filtering of the permission-denied error messages a separate task that you want to be able to apply to any find command, then the opposite approach of proactively preventing permission-denied errors requires introducing "noise" into the find command, which also introduces complexity and logical pitfalls.
      • For instance, the most up-voted comment on Michael's answer (as of this writing) attempts to show how to extend the command by including a -name filter, as follows:
        find . ! -readable -prune -o -name '*.txt'
        This, however, does not work as intended, because the trailing -print action is required (an explanation can be found in this answer). Such subtleties can introduce bugs.
  • The first solution in Jonathan Leffler's answer, find . 2>/dev/null > files_and_folders, as he himself states, blindly silences all error messages (and the workaround is cumbersome and not fully robust, as he also explains). Pragmatically speaking, however, it is the simplest solution, as you may be content to assume that any and all errors would be permission-related.

  • mist's answer, sudo find . > files_and_folders, is concise and pragmatic, but ill-advised for anything other than merely printing filenames, for security reasons: because you're running as the root user, "you risk having your whole system being messed up by a bug in find or a malicious version, or an incorrect invocation which writes something unexpectedly, which could not happen if you ran this with normal privileges" (from a comment on mist's answer by tripleee).

  • The 2nd solution in viraptor's answer, find . 2>&1 | grep -v 'Permission denied' > some_file runs the risk of false positives (due to sending a mix of stdout and stderr through the pipeline), and, potentially, instead of reporting non-permission-denied errors via stderr, captures them alongside the output paths in the output file.

mklement0
  • 245,023
  • 45
  • 419
  • 492
  • 4
    Just a quick question: why do you use a process substitution and not just a pipe: `find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2`? – gniourf_gniourf Dec 25 '16 at 20:56
  • 2
    @LéoLéopoldHertz준영: If you don't want to output to an external file, just do more plumbing: `{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1` – gniourf_gniourf Dec 25 '16 at 22:12
  • 2
    @LéoLéopoldHertz준영: Just that it's POSIX compliant. Process substitutions `>(...)` are Bash-specific. – gniourf_gniourf Dec 25 '16 at 22:24
  • 2
    I'm not sure that the preservation of the exit code of `find` should be emphasized and advertised: `find`'s exit code is notoriously useless. Here, it's very likely going to be non-zero (and uselessly so). – gniourf_gniourf Dec 26 '16 at 12:57
  • 1
    Why is this "reasonable simple" compared to "find . ! -readable ..."? It uses process substitution and grouping commands, what make things more complicated & what is maybe not needed for Why should one use only POSIX compliant find features - but use bash or zsh at the same time? From my point of view the argument should be the operating system: GNU/Linux vs BSD vs macOS. How is your solution better compared to Jonathan Leffers answer? There is much more complexity added / much more text to read without any substantial benefit. – Michael Brux Dec 29 '16 at 09:20
  • From my point of view the issue about "doesn't silence all Permission denied errors" can be an porting error or an error in macOS or an error in the underlying file system - but is no general argument against "find . ! -readable ...". Or not an argument against it in a GNU/Linux environment. – Michael Brux Dec 29 '16 at 09:25
  • 3
    POSIX explicitly requires the `execute/search` file-mode permission in order to 'search' a directory (retrieve the inodes of contained files). `find` does this in order to descend into a subdirectory (in addition to requiring `read` permission to list the files in a directory). This is not a 'bug' or 'porting error'. – wjordan Dec 30 '16 at 04:49
  • 1
    GNU/Linux vs. POSIX-environment discussion aside, I don't see how adding command-line options to the `find` command 'pollutes', 'obscures the actual intent', or makes it any 'harder to extend' - especially when being compared directly with alternative solutions involving pipelines, additional utilities, error-stream redirection, etc. – wjordan Dec 30 '16 at 04:58
  • 1
    GNU `find` can be installed on macOS: `brew install findutils`. – Henrique Gontijo Mar 02 '19 at 16:50
  • TLDR, find . -name myname 2>&1 | grep -v "Permission denied" (when not building a rocket ship, but trying to find a file) – Rusty75 Jun 09 '20 at 10:16
115

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:

  1. 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.

  1. 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
    
  2. 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'
    
Fatih Aksu
  • 3,373
  • 2
  • 19
  • 19
98

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.

Dave Jarvis
  • 28,853
  • 37
  • 164
  • 291
Jeremy
  • 989
  • 6
  • 2
  • 3
    @Masi, the command in the answer doesn't use `expect`. Instead, `expect` is simply the name of the file that this command will try to find. – Dhruv Kapoor Feb 10 '14 at 08:30
  • 2
    Blindly redirecting all stderr output just to ignore a single class of error messages is generally a bad idea - you will lose all other arbitrary errors in the process. – Josip Rodin Sep 24 '15 at 12:18
62

Pipe stderr to /dev/null by using 2>/dev/null

find . -name '...' 2>/dev/null

Micah Smith
  • 3,606
  • 19
  • 25
Matt
  • 2,091
  • 11
  • 9
30

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
Community
  • 1
  • 1
sdaau
  • 32,015
  • 34
  • 178
  • 244
  • 4
    `-perm -g+r,u+r,o+r` merely matches files that have the `r` (read) permission set for all 3 of the _file's_ security principals, which has no direct relationship with whether the _current user_ can read that file or not. It has the potential to both miss files that the current user _can_ read and to match files that they cannot. – mklement0 Oct 24 '16 at 03:33
  • I think `find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -print` would be the good solution. – Mattia72 Nov 29 '16 at 09:16
  • 2
    @Mattia72: No, it is fundamentally impossible to fully emulate `-readable` with `-perm` - see my previous comment and consider this example: `echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=r` prints `file`, because its user read bit is set, but it relates to the the `nobody` user, not the current user. The current user cannot read this file; try `cat file`. See also: [this answer](http://stackoverflow.com/questions/4458120/unix-find-search-for-executable-files/29039160#29039160) of mine. – mklement0 Jan 16 '17 at 20:02
23

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
Jason Coco
  • 76,627
  • 20
  • 180
  • 178
20

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.

Léo Léopold Hertz 준영
  • 119,377
  • 159
  • 417
  • 655
Bunti
  • 1,607
  • 15
  • 19
  • Nice binding to the OS X! Jonathan's answer explains the part `2>/dev/null`. Can you please explain the part `-exec du -ch {} + 2>/dev/null | grep total$`. – Léo Léopold Hertz 준영 Feb 02 '16 at 09:58
  • 1
    @Masi You can use any command with `-exec` option to take further action on the files or directories found by `find` command. `du -ch file_pattern` calculates the size of each file matching `file_pattern` and last line of that output is the grand total of all files that matched the `file_pattern`. See man page for `du`. `grep total` just filters the line that extracts the grand total(which is the last line). – Bunti Feb 02 '16 at 22:23
13

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
viraptor
  • 30,857
  • 7
  • 96
  • 176
12

Simple answer:

find . > files_and_folders 2>&-

2>&- closes (-) the standard error file descriptor (2) so all error messages are silenced.

  • Exit code will still be 1 if any 'Permission denied' errors would otherwise be printed

Robust answer for GNU find:

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 (-typed) 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 standard
  • May still return 'Permission denied' on abnormal/corrupt files (e.g., see bug report affecting container-mounted filesystems using lxcfs < v2.0.5)

Robust answer that works with any POSIX-compatible 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.

  • Will also filter any 'Permission denied' errors due to output redirection (e.g., if the files_and_folders file itself is not writable)
wjordan
  • 17,115
  • 2
  • 72
  • 91
  • How do you think about JordiFerran's answer proposal? - - Can you compare your answer to it? – Léo Léopold Hertz 준영 Dec 25 '16 at 09:13
  • 2
    That answer's shell script as stated is not general-purpose (only lists directories matching ${m_find_name}), and contains several options not relevant to the question (nice, /home*, -maxdepth 5, -follow). This answer addresses the specific issue of 'filtering readable but not executable directories' more concisely, while remaining general-purpose. – wjordan Dec 25 '16 at 13:23
  • 1
    @wjordan: Thanks. I've removed my comments, but one point still applies: the `-perm`-based solution is not worth presenting, because it more fundamentally than the quote suggests does something _different_ than intended: it is a purely _file-centric_ test, relating to the _file's_ owner and group, neither of which have any guaranteed relationship with the user calling the command (see [this answer](http://stackoverflow.com/a/29039160/45375) of mine. It looks like your revised GNU solution now doesn't catch permission denied errors stemming from _files_. – mklement0 Dec 25 '16 at 20:43
  • I don't recognize the syntax you're using (neither as GNU nor as BSD), but let me illustrate my point with a self-contained example: `echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=r` prints `file`, because its user read bit is set, but it relates to the the `nobody` user, not the current user. The current user cannot read this file; try `cat file`. – mklement0 Dec 25 '16 at 23:41
  • 1
    @mklement0 thanks for the discussion, i managed to produce the behavior you described in another test (don't know what I did wrong the first time), it does seem that `-perm` doesn't work for determining the user's current permissions. Removed that alternative from this answer. – wjordan Dec 26 '16 at 06:09
4

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).

simpleuser
  • 1,419
  • 19
  • 28
4

use

sudo find / -name file.txt

It's stupid (because you elevate the search) and nonsecure, but far shorter to write.

mist
  • 1,835
  • 2
  • 19
  • 33
  • You search here the whole filesystem so you mean by this "elevate the search". Why do you call it nonsecure? Because it is searching whole filesystem? – Léo Léopold Hertz 준영 Dec 16 '14 at 12:06
  • 2
    Because sudo runs the find command with root permissions which basically is a bad idea. Segregation and least-privilege principles are violated. – mist Dec 16 '14 at 12:22
  • 3
    The "elevation" here is of the privileges, to root, with `sudo`. You risk having your whole system being messed up by a bug in `find` or a malicious version, or an incorrect invocation which writes something unexpectedly, which could not happen if you ran this with normal privileges. – tripleee Dec 07 '15 at 05:34
2

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.

  • ¿Why using command nice? I got the idea here. Initially I thought it would be nice to reduce process priority when looking an entire filesystem. I realized it makes no sense to me, as my script is limited to few directories. I reduced -maxdepth to 3.
  • ¿Why search within /home*/? This it not relevant for this thread. I install all applications by hand via source code compile with non privileged users (not root). They are installed within "/home". I can have multiple binaries and versions living together. I need to locate all directories, inspect and backup in a master-slave fashion. I can have more than one "/home" (several disks running within a dedicated server).
  • ¿Why using -follow? Users might create symbolic links to directories. It's usefulness depends, I need to keep record of the absolute paths found.
Community
  • 1
  • 1
Jordi Ferran
  • 129
  • 3
  • Thank you for your answer and nice observations! I opened a bounty here to preview your answer better. I think it is a nice finding not prevent read and execute access. - - Can you please explain why you use `nice` and `find $HOME -maxdepth 5 -follow ...`? – Léo Léopold Hertz 준영 Dec 22 '16 at 11:21
  • 2
    The shell script as stated is not general-purpose (only lists directories matching `${m_find_name}`), and contains several options not relevant to the question (`nice`, `/home*`, `-maxdepth 5`, `-follow`). I've added an answer that addresses the specific issue of 'filtering readable but not executable directories' more concisely, while remaining general-purpose. – wjordan Dec 25 '16 at 04:33
2

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

Leonardo Hermoso
  • 808
  • 11
  • 24
2

-=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

Jan aka uptech
  • 921
  • 7
  • 12
1

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.

Kayle Sawyer
  • 469
  • 7
  • 19
  • I want to grep all txt files and exclude hidden files/directory, omit "Permission denied" message to be printed. I am using csh shell. I have used below commands and they are not working find . -type f -iname "*.txt" -not -path '*/\.*' | egrep -v "Permission denied" find . -type f -iname "*.txt" -not -path '*/\.*' 2>/dev/null Getting below Error. find: paths must precede expression: 2 Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression] – yadav May 11 '20 at 10:26