bug-findutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: execdir plus and commands generated


From: James Youngman
Subject: Re: execdir plus and commands generated
Date: Sat, 2 Apr 2011 13:30:44 +0100

On Tue, Mar 29, 2011 at 4:56 AM, Peggy Russell
<address@hidden> wrote:
> Hi,

Hi, and thanks for the careful and detailed bug report.

> Why does `find` process file 'abc4' separately from files 'abc1-3',
> when they are in the same directory.

The answer is that it is a shortcoming in the design of find, but this
is best explained just after the evidence you show that illustrates
the problem.  So, please read on.

> This creates  3 `rm` commands
> instead of 2 (assuming it looks like a `rm` for all files per
> directory)? Files 'abc1-4' are in the current directory. File 'def1'
> is in a sub directory.  Is there a way to get `execdir +` to produce
> 1 `rm` like `xargs` (see below)?
>
> Here's the Test Data:
>  mkdir -p test/bar
>  touch test/abc{1,2,3,4}.txt test/bar/def1.txt test/"s p a c e.txt"
>  cd test
>  run find command
>
>  find . -name "*" -printf '[%y] %-20p%i\n'
>  [d] .                   60104719
>  [f] ./abc4.txt          60104730     <--- 1st rm
>  [d] ./bar               60104720
>  [f] ./bar/def1.txt      60104731     <--- 2nd rm
>  [f] ./abc3.txt          60104728     <--- 3rd rm
>  [f] ./s p a c e.txt     60104732          |
>  [f] ./abc2.txt          60104722          |
>  [f] ./abc1.txt          60104721          |
>
> Here's the Find Command:
>
>  find . -type f -name "*.txt" \
>    -execdir bash -c 'echo "+++Deleting $@ - $(pwd)"; rm "$@"' dmy {} +
>
>  +++Deleting ./abc4.txt - /project/test/test
>  +++Deleting ./def1.txt - /project/test/test/bar

What's happening here is that find has changed directory into the bar
subdirectory.

find, as currently implemented, only has one data structure per
command-line -execdir predicate for accumulating new arguments.   So,
when we descended into project/test/test/bar we cleared the current
list of arguments by executing the command, in order to make room for
./def1.txt.   Clearly this is not strictly necessary, we could just
use a different list.   However, I have not yet made this change to
find.

The analogous problem does not occur for -exec ...+, because we can
use one list for everything, since commands run by -exec all have the
same working directory.

To be honest, I *hope* to fix this problem, but I do not have a *plan*
to fix it any time soon; I'm a bit short of time to do this.    Still,
if this is an issue you care about enough to help fix it and are
willing to donate the copyright in your changes to the GNU project, I
would be happy to accept your bug-fixing patch.

>  +++Deleting ./abc3.txt ./s p a c e.txt ./abc2.txt ./abc1.txt
>     - /project/test/test
>
> I often see it recommended to use xargs instead of exec/execdir, and
> wonder if that still applies...

For security reasons the findutils documentation doesn't recommend
that.  In fact, it quite carefully explains the security downsides of
using xargs for this kind of thing.


> The `xargs` below produced 1 `rm` command. It seems to be a complement
> with benefits to the above `-execdir +` which produced 3 `rm`.
>
>  time find . -type f -name "*.txt" -print0 |
>    xargs -0  bash -c 'echo "+++Deleting $@ - $(pwd)"; rm "$@"' --
>
> The `xargs` (-I{} implies -L1) and `execdir \;`  below each produced
> 6 `rm` commands each.
>
>  find . -type f -name "*.txt" \
>    -execdir bash -c 'echo "+++Deleting {} - $(pwd)"; rm "{}"' \;
>
>  find . -type f -name "*.txt" -print0 |
>    xargs -0I {} bash -c 'echo "+++Deleting {} - $(pwd)"; rm "{}"'

These should differ in the result of $(pwd) of course.

Thanks,
James.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]