0

I want to perform checks on all files in the system. For that I need the full paths of all files in the system. My initial idea was to do something like this:

for file in $(sudo find / ); do
   if [ -d $file ]; then

and so on.

But then I read that it's bad practice to process the output of find that way. What then is the correct way?

(I tried things like ls -RF | grep "/$". That, however, only gives me the directory names but I need the full path of every file, directory etc. in the system.)

closed as unclear what you're asking by Kusalananda, Mr Shunz, X Tian, roaima, Jesse_b Feb 8 at 14:31

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • You seem a bit conflicted about what you're looking for: title, initial find command, and the end of the body all point to "every file (and directory)", but your test -d and grep /$ indicate only directories. What are you actually trying to do? – Jeff Schaller Feb 7 at 15:08
  • The -d and the grep /$ were just examples - the ls -F adds a character to the filename also for file types other than directories and the -R lists recursively but only displays filenames, grouped by directories. Ultimately I need to list the full paths of all files in the system and invoke a variety of the conditional operators on them (-d, -s, -L, -p etc.) I was looking for an option to ls that does that but all I found was ls -RF. – Arjen Feb 7 at 15:24
  • @Arjen If you have clarifications to your question, then update the question, don't add information in comments. – Kusalananda Feb 7 at 15:26
  • @Kusalananda I responded to Jeff Schaller's comment. – Arjen Feb 7 at 15:29
  • if you extended your [ if -d .. example to show the various operators, it'd be clearer that you don't need a simple find -type d – Jeff Schaller Feb 7 at 15:39
2

Use the -exec option of find. Your sample script would be written as:

sudo find / -type d -exec myprog {} \;

The {} will be replaced by each file (directory in this case) found.

If you want to do different things on each entry depending on whether it's a directory or regular file or whatever, you can put that logic into "myprog.sh" or just call find multiple times with different -type selections.

EDIT: For a single-instance script option, write myprog as:

#! /bin/bash -

while IFS= read -rd '' FILE; do
    if [ -d "$FILE" ]; then
    ...
done

And call

find / -print0 | myprog

(or replace -print0 with -exec printf '%s\0' {} + if your find doesn't support -print0).

  • Don't use -type d. They want all files (and directories, and, I presume, sockets etc. too). – Kusalananda Feb 7 at 14:42
  • @Kusalananda Like I said, the type d is to model their sample script (replacing the test -d). It was just an example. As I also said, if they want all, they can move that logic to their script. – L. Scott Johnson Feb 7 at 14:44
  • Yes, thanks. Indeed I now use a myprog version that performs all the tests I need on $1. But now that program is invoked for every object found and that will take considerably longer. And the other problem is that myprog has no memory of what happened before. What if I just want to count the finds? As far as I understand I can't just update an environment variable with a count. I could add a character to a disk file for every find and then do a wc -c < disk_file later. Feels a bit messy. Is there a better way to do that? – Arjen Feb 7 at 15:11
  • xargs is one way to pass many files to a single program. find / -print | xargs myprog Or just write myprog to read filenames from standard input and pipe directly to it. – L. Scott Johnson Feb 7 at 15:15
  • @Arjen What is it that you actually want to do? Please update your question. – Kusalananda Feb 7 at 15:25
0

If you want to print all the files

find / -type f
  • almost; the OP is trying to clarify, but currently says but I need the full path of every file, **directory** etc. in the system -- it appears that they want to independently check each "file" for whether it's a file, directory, (socket?), etc – Jeff Schaller Feb 7 at 18:31
  • @Praveen Thanks Praveen, but 'f' stands for regular files. However, I need all files - including character and block devices, directories, pipes, symbolic links, sockets. I also want to do tests for for 'executable', 'readable', 'writeable', group-id-bit, user-id-bit, ... so I really need everything. According to some opinion Linux treats 'everything' as a file, so I thought the formulation 'all filenames' would suffice. Apparently that isn't the case. – Arjen Feb 8 at 3:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.