Bug 237030

Summary: ls -R produces invalid output when recursing dot directories
Product: Base System Reporter: Duane <parakleta>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: New ---    
Severity: Affects Some People CC: emaste
Priority: ---    
Version: 11.2-STABLE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
Patch to skip recursion of dot directories none

Description Duane 2019-04-05 02:43:00 UTC
Created attachment 203394 [details]
Patch to skip recursion of dot directories

`ls -R` doesn't print dot directories (i.e. those with a '.' prefix) nor their contents but it still recurses through them and will print the contents of directories within.

The standard could be argued as ambiguous on this point (see bug #206192), but generally the agreement is that this is the wrong behaviour.  Note additionally that FreeBSD doesn't exhibit either of the described behaviours because it doesn't print the contents of a dot directory, only the contents of non-dot-directories contained in dot-directories.

As an example set up a directory as follows: `mkdir test; cd test; git init`

Then `ls -R` outputs the following:
<-->
    applypatch-msg.sample*     pre-applypatch.sample*     pre-rebase.sample*         update.sample*
    commit-msg.sample*         pre-commit.sample*         pre-receive.sample*
    post-update.sample*        pre-push.sample*           prepare-commit-msg.sample*

    ./.git/info:
    exclude

    ./.git/objects:
    info/ pack/

    ./.git/objects/info:

    ./.git/objects/pack:

    ./.git/refs:
    heads/ tags/

    ./.git/refs/heads:

    ./.git/refs/tags:
<-->

Now run `touch file; ls -R` and the result changes as follows:
<-->
    file

    ./.git/branches:

    ./.git/hooks:
    applypatch-msg.sample*     pre-applypatch.sample*     pre-rebase.sample*         update.sample*
    commit-msg.sample*         pre-commit.sample*         pre-receive.sample*
    post-update.sample*        pre-push.sample*           prepare-commit-msg.sample*

    ./.git/info:
    exclude

    ./.git/objects:
    info/ pack/

    ./.git/objects/info:

    ./.git/objects/pack:

    ./.git/refs:
    heads/ tags/

    ./.git/refs/heads:

    ./.git/refs/tags:
<-->

Notice the extra directories that are now output that weren't before.

The solution is quite simple, to just skip the recursion in the event that the directory's children are skipped, and attached is a patch which does just that.
Comment 1 Duane 2019-04-05 21:54:46 UTC
Just a point of interest, it appears this bug was present in the BSD4.4 sources, and Apple only just fixed it around 2014 in their fork with the same change as I have proposed.  See https://opensource.apple.com/source/file_cmds/file_cmds-242/ls/ls.c.auto.html