-4

I have to make a script which prints the sizes of all .conf files from /etc recursively in a specified file, and that prints the errors caused by the lack of permission in another file. I don't know how to make it. Any suggestion would be very helpful.

Eliah Kagan
  • 119,640

3 Answers3

1

You can use -fprintf to write output from find to a file.

$ find /etc -type f,l -name '*.conf' \
    -fprintf ~/filelist '%s %p\n' 2> ~/error.log

find options:

  • -type f,l Search for regular files and symbolic link.
  • -name Match the base of the file name with shell match pattern.
  • -fprintf Like -printf but writes output to a file instead.

fprintf format:

  • %s File's size in bytes.
  • %p File's name (with starting-point included).
  • \n Newline.

Bash:

  • [n]>file Redirect file descriptor [n] to "file".
  • ~ Expands to the value of the shell parameter HOME.
  • \ Breaks a up long lines into multiple lines.
0

As mentioned in comment find and printf are your friends on this homework assignment. For a one-liner use:

find /etc -name "*.conf" -printf "%s %p\n" 1>namesize.txt 2>errors.txt

To test the components with output to your screen try out the examples below.

$ find /etc -name "*.conf" 1>/dev/null
find: ‘/etc/ssmtp’: Permission denied
find: ‘/etc/polkit-1/localauthority’: Permission denied
find: ‘/etc/cups/ssl’: Permission denied
find: ‘/etc/ssl/private’: Permission denied

This is the short one that shows permission denied. Regular output is redirected to /dev/null (nowhere) so you get to see only the error messges.

$ find /etc -name "*.conf" -printf "%s %p\n" 2>/dev/null | column -t
3874   /etc/bluetooth/main.conf
258    /etc/bluetooth/proximity.conf
397    /etc/bluetooth/input.conf
  (... SNIP ...)
1366   /etc/at-spi2/accessibility.conf
13592  /etc/openal/alsoft.conf
1800   /etc/cracklib/cracklib.conf

This shows the the list of filenamnes and sizes which is too long to print entirely. The four error messages for "Permission denied" are filtered out with 2>/dev/null redirecting all errors to "nowhere".

Output is piped (using |) to the column -t command which pads spaces behind the file sizes in order for the filenames to align in the output.


Compare links to other answer

The other answer shows links like this:

$ find -L /etc -type f -name '*.conf' -fprintf ~/filelist '%s %p\n' 2> ~/error.log
$ grep 45-latin.conf ~/filelist | column -t
4621  /etc/fonts/conf.d/45-latin.conf
4621  /etc/fonts/conf.avail/45-latin.conf

The size of the link inherits the size of the file it points to.

My answer shows links like this:

$ find /etc -name "*.conf" -printf "%s %p\n" 1>namesize.txt 2>errors.txt
$ grep 45-latin.conf namesize.txt | column -t
27    /etc/fonts/conf.d/45-latin.conf
4621  /etc/fonts/conf.avail/45-latin.conf

The size of the link is the real size of the link (27 bytes).

So it's a question of how your professor/TA/teacher wishes to links reported in the answer. The homework/Lab assignment should have been more specific on how to handle such intricacies of Linux.

To look at the link use:

$ ll /etc/fonts/conf.d/45-latin.conf
lrwxrwxrwx 1 root root 27 Aug  2  2018 /etc/fonts/conf.d/45-latin.conf -> ../conf.avail/45-latin.conf
0

You can use bash’s globstar option:

If set, the pattern ** used in a pathname expansion context will match all files and zero or more directories and subdirectories. If the pattern is followed by a /, only directories and subdirectories match.

Set it with:

shopt -s globstar

After that you can match any .conf file under /etc with /etc/{,**/}*.conf, so now a simple stat call is enough to solve the task, e. g. for size and filename separated by space:

stat -c '%s %N' /etc/{,**/}*.conf

To redirect the output of that, use >file for stdout and 2>file for stderr, e. g.:

stat -c '%s %N' /etc/{,**/}*.conf >~/stdout 2>~/stderr

As the glob doesn’t match any directory for which you don’t have the proper permissions you normally don’t get any permission errors though, but those files are just skipped instead. To list them you can use find and search for matching files not matching the o+r permission, i. e. not readable by others:

sudo find /etc -type f -name '*.conf' ! -perm -o+r

Further reading

dessert
  • 40,956