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

7
  • 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
    Commented Feb 7, 2019 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
    Commented Feb 7, 2019 at 15:24
  • @Arjen If you have clarifications to your question, then update the question, don't add information in comments.
    – Kusalananda
    Commented Feb 7, 2019 at 15:26
  • @Kusalananda I responded to Jeff Schaller's comment.
    – Arjen
    Commented Feb 7, 2019 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
    Commented Feb 7, 2019 at 15:39

2 Answers 2

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

6
  • Don't use -type d. They want all files (and directories, and, I presume, sockets etc. too).
    – Kusalananda
    Commented Feb 7, 2019 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. Commented Feb 7, 2019 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
    Commented Feb 7, 2019 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. Commented Feb 7, 2019 at 15:15
  • @Arjen What is it that you actually want to do? Please update your question.
    – Kusalananda
    Commented Feb 7, 2019 at 15:25
0

If you want to print all the files

find / -type f
2
  • 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
    Commented Feb 7, 2019 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
    Commented Feb 8, 2019 at 3:00

Not the answer you're looking for? Browse other questions tagged .