[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Regression: "find dir/. -type d -empty -delete" claims 'unsuccessful
Re: Regression: "find dir/. -type d -empty -delete" claims 'unsuccessful', breaking scripts.
Mon, 18 Nov 2013 20:34:27 -0800
On 18/11/2013 20:04, Eric Blake wrote:
On 11/18/2013 06:20 PM, Linda Walsh wrote:
>>> However, "find dir/. -type d -empty -delete" works, but exits with
>>> a failure code causing scripts to break.
>> This behavior is required by POSIX. Sorry.
POSIX requires that whatever you pass on the command line ("dir/.") be
passed as the prefix to all paths traversed by find; therefore, find must
traverse "dir/.". POSIX also requires that remove("dir/.") must fail.
But not until the very end. As specifying --delete also requires -depth.
> It sure looks like POSIX does NOT require it. "-delete" is a gnu
> extension, so it wouldn't be covered either.
But it is. When you "copy -al a/. b/." , it doesn't really copy or link
the directory inodes themselves, but the contents of a and b. However if
you try to "mv a/. b/.", that DOES fail as you are trying to rename a to
b which already exists..
Since "." is a "well-known starting point, used in most find examples --
I assert that pathname/. is the tar equivalent of setting the starting path
and then doing your find from.
Right, but it makes no sense to handle -delete as though it were visiting
"dir" instead of "dir/.", nor to be inconsistent with what you would get
with the POSIX behavior of "find dir/. | xargs rmdir" (at least, when
there are no directories with space/newline issues in that tree).
Ah... but it does! "-delete" is doing the function of "remove" which works
on both files and dirs... so your above example "find dir/..|xargs remove
-- would work. -delete = remove, not unlink nor rmdir. They've also said
that "remove" functions like and gets the errors of "unlink or rmdir
depending on which applies -- that implies that it wouldn't get the same
errors if the "AT" flag was set in the remove call as it is described as
being settable in the unlink and rmdir calls.. (unlinkat, rmdirat =>
removeat). But that's an aside. remove wouldn't get an error in your
example -- and it doesn't touch on the problem of deleting the directory
you are "in", as you are deleting a subdir which could go away...
> So I ask where you get the idea that it is required by POSIX.
POSIX requires what gets visited, and the GNU extension of -delete
determines the actions attempted on the places visited; since -delete
implies remove(), and since remove("dir/.") is required to fail, it is
the only logical behavior, even if the extension itself is not required
You visit it -- that's fine remove can delete directories OR files.
It's Very similar to how rm -fr . used to work -- but with rm -fr ., the -f
would silence the error and any non-zero return val. So add a "-f" flag
that has to be before any patterns to go along with "-delete" that does the
same thing -- it silences the errors and lets it return w/o status. I'd be
fine with that as a solution -- you get your error in the normal case, and
I can add "-f" to force-or-ignore (ignore being the pertinent option in
this case ;-)).
Otherwise, you are generating an error that makes no difference other than
to make the command fail -- and there is no way to tell from the status if
the command failed due to other things not being deleted or if it was just
that final dir which one, not only wouldn't care about -- but wouldn't
really want deleted. (i.e. if you want to take the dir as well just do
your find on "dir" w/o the "/.")....
Does that sound reasonable and consistent?