2

I am trying to get ls like output from find command (this is on Linux Mind with find (GNU findutils) 4.7.0.

This is because I want to see the numerical chmod permissions.

What I managed so far is:

% find . -maxdepth 1 -printf "%m %M %y %g %G %u %U %f %l\n"
755 drwxr-xr-x d blueray 1000 blueray 1000 . 
664 -rw-rw-r-- f blueray 1000 blueray 1000 .zshrc 
644 -rw-r--r-- f blueray 1000 blueray 1000 .gtkrc-xfce 
644 -rw-r--r-- f blueray 1000 blueray 1000 .sudo_as_admin_successful 
777 lrwxrwxrwx l root 0 root 0 resolv.conf /run/systemd/resolve/resolv.conf

Here, %l print empty string if file is not a symbolic link.

What I am looking for is, if %l is not empty then print -> %l.

How can I do that with -printf?

7
  • 1
    This might help with GNU find: find -maxdepth 1 -ls
    – Cyrus
    Jan 28 at 21:24
  • @Cyrus yeah, my first thought too but that doesn't show the octal file permissions which is what the OP is doing this for.
    – terdon
    Jan 28 at 21:28
  • 1
    If what you care about is the permissions, I'd get that directly from GNU stat (which can be told to emit them via its more-expressive format string syntax). Jan 29 at 15:49
  • 1
    Given your real use case, is there any reason you're asking for ls-like output, instead of just asking for numerical permissions and filenames (and potentially nothing else)? Jan 29 at 15:50
  • 1
    @blueray, stat doesn't list files at all -- it requires something else to give it the list. So, f/e, in stat *, it's not stat deciding what files are included in *, it's your shell making that decision; you can make your shell include hidden files in * by changing its configuration, or you can tell find to pass filenames to stat with something like find . -exec stat ... {} +, substituting ... with the arguments you choose. Jan 30 at 17:09

1 Answer 1

10

You can tell find to print one thing for links and another for non links. For example:

$ find  . -maxdepth 1 \( -not -type l -printf "%m %M %y %g %G %u %U %f\n" \) -or \( -type l -printf "%m %M %y %g %G %u %U %f -> %l\n" \) 
755 drwxr-xr-x d terdon 1000 terdon 1000 .
644 -rw-r--r-- f terdon 1000 terdon 1000 file1
755 drwxr-xr-x d terdon 1000 terdon 1000 dir
644 -rw-r--r-- f terdon 1000 terdon 1000 file
777 lrwxrwxrwx l terdon 1000 terdon 1000 linkToFile -> file

Or, a little more legibly:

find  . -maxdepth 1 \( -not -type l -printf "%m %M %y %g %G %u %U %f\n" \) \
                -or \( -type l -printf "%m %M %y %g %G %u %U %f -> %l\n" \) 

The \( -not -type l -printf '' ... \) will be run for anything that isn't a symlink, while the -or \( -type l -printf '' ...\) will be run for symlinks only.

2
  • Or you could pipe it to xargs stat
    – waltinator
    Jan 29 at 19:51
  • 1
    @waltinator, find ... | xargs stat is quite severely buggy, unless you mean find ... -print0 | xargs -0 stat. By default, xargs treats quotes and backslashes as syntactic rather than literal, word-splits on spaces, provides no means whatsoever to escape literal newlines, and otherwise can't correctly handle a wide variety of legitimate file names. Better to just use find ... -exec stat ... {} +, so find itself is running stat (using {} + instead of {} \; buys one the same performance benefits xargs provides in terms of running the fewest necessary copies of stat) Jan 30 at 17:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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