bugfindutils - Bugs: bug #46305, Doing "find -L . -type d...


bug #46305: Doing "find -L . -type d -delete" fails on symlinks to directories.

Submitted by:  C <pfudd>
Submitted on:  Tue 27 Oct 2015 01:23:12 AM UTC
Category:  find Severity:  4 - Important
Item Group:  Wrong result Status:  Wont Fix
Privacy:  Public Assigned to:  jay
Originator Name:  Open/Closed:  Open
Release:  4.4.2 Fixed Release:  None
* Mandatory Fields

Add a New Comment (Rich Markup)

Comment Type & Canned Response:


Mon 16 Jul 2018 08:46:59 PM UTC, comment #3: 

With "-L bar -delete", find would have to delete 2 files:
a) the symlink target '../foo', and
b) the symlink itself 'bar/baz'.

I agree with James that trying to fix (or work around) this
would probably more ask for trouble than being of help.

From 'man find':

  -L   ... Actions that can cause  symbolic  links  to  become
       broken while find is executing (for example -delete)
       can give rise to confusing behaviour.

Depending on where the symlink points to, deleting possibly
the opposite way up the tree sounds too dangerous IMO; consider:
  ln -s ../../../../../../..  kllr-slink
or the 'symlink-to-root' example James gave.

Finally, also rm(1) and rmdir(1) do not have an -L option - probably
for a good reason.

Have a nice day,

Bernhard Voelker <berny>
Project Administrator
Thu 12 Jul 2018 03:45:53 AM UTC, comment #2: 

I think this is an actual bug, despite the general danger of running -delete together with -L.  In this setup:

$ mkdir foo
$ mkdir bar
$ ln -s ../foo bar/baz
$ find -L bar -delete
find: cannot delete ‘bar/baz’: Not a directory
find: cannot delete ‘bar’: Directory not empty

(No -type d necessary.)  strace shows that find tried to

unlinkat(AT_FDCWD, "bar/baz", AT_REMOVEDIR) = -1 ENOTDIR (Not a directory)

but "bar/baz" is not a directory so AT_REMOVEDIR is wrong.

Tavian Barnes <tavianator>
Sun 01 Nov 2015 09:23:19 PM UTC, comment #1: 

> The '-L' option makes '-type d' detect symlinks to directories, but '-delete' doesn't treat them as such.

I don't think that's what is happening.  Use of -delete automatically turns on -depth.  This means that the filesystem is visited in postorder.  For the command line " find -L . -type d -delete" this means that the -delete action takes place for children and some siblings before it takes place for some item.   In the case of symbolic links this will mean that, at least some of the time, the thing the link points to will have been deleted before the link is examined by find.

That means that, at the time bar (in your example) is examined, "-type d" is no longer true for it.  It's a broken symlink instead (-type l would match it) and so it is not deleted since -type d is false.

I don't think this problem can be "solved" by special-casing directories, as I'd imagine that analogous things apply to link counts or (sometimes) directory sizes.

I think then that find is working as designed and that changing this aspect of the design to change this behaviour would likely give rise to semantics that are both inconsistent and much harder to explain (because of the special-casing).

I'd recommend simply avoiding the use of -L with -delete (and in any case that combination risks causing the deletion of unexpected  parts of the tree where third parties can make symbolic links to / for example).

Please feel free to follow up if you disagree or you can see a simple solution.   In the meantime I will work on some documentation updates to try to make things clearer.

James Youngman <jay>
Project Administrator
Tue 27 Oct 2015 01:23:12 AM UTC, original submission:  

The '-L' option makes '-type d' detect symlinks to directories, but '-delete' doesn't treat them as such.

$ mkdir /tmp/foo
$ cd /tmp/foo
$ mkdir baz
$ ln -s baz bar
$ find -L . -type d
$ find -L . -type d -delete
find: cannot delete `./bar': Not a directory
$ ls -l
total 0
lrwxrwxrwx 1 root root 3 Oct 26 18:12 bar -> baz

I'd expect --delete to delete whatever it found.

Note: if 'bar' is the directory and 'baz' is the symlink, then no error message is generated, but baz remains as a broken symlink, since the directory was deleted before the symlink was found (assuming sorted directory traversal).

Also, http://ftp.gnu.org/gnu/findutils/ indicates that 4.4.2 is the latest version (from 2009), but this bug-reporting page indicates that 4.5.14 is the latest version.  Please link to the new download page on https://savannah.gnu.org/projects/findutils/, or expect bug reports about ancient versions of the code.  :-)


C <pfudd>


(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:

Attached Files
file #35360:  sv-43605-base.sh added by jay (2KiB - application/x-shellscript)


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -email is unavailable- added by berny (Posted a comment)
  • -email is unavailable- added by tavianator (Posted a comment)
  • -email is unavailable- added by jay (Updated the item)
  • -email is unavailable- added by pfudd (Submitted the item)

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.





    Follow 4 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2015-11-01 jay Attached File- => Added sv-43605-base.sh, #35360
    2015-11-01 jay StatusNone => Wont Fix
    2015-11-01 jay Severity3 - Normal => 4 - Important
        Assigned toNone => jay

    Back to the top

    Powered by Savane 3.9