On 4 April 2014 12:16, Chris Angelico <ros...@gmail.com> wrote:
> On Fri, Apr 4, 2014 at 11:15 AM, David <bouncingc...@gmail.com> wrote:
>> On 4 April 2014 01:17, Chris Angelico <ros...@gmail.com> wrote:
>>>
>>> -- Get info on all .pyc files in a directory and all its subdirectories --
>>> C:\>dir some_directory\*.pyc /s
>>> $ ls -l `find some_directory -name \*.pyc`
>>>
>>> Except that the ls version there can't handle names with spaces in
>>> them, so you need to faff around with null termination and stuff.
>>
>> Nooo, that stinks! There's no need to abuse 'find' like that, unless
>> the version you have is truly ancient. Null termination is only
>> necessary to pass 'find' results *via the shell*. Instead, ask 'find'
>> to invoke the task itself.
>>
>> The simplest way is:
>>
>>     find some_directory -name '*.pyc' -ls
>>
>> 'find' is the tool to use for *finding* things, not 'ls', which is
>> intended for terminal display of directory information.
>
> I used ls only as a first example, and then picked up an extremely
> common next example (deleting files). It so happens that find can
> '-delete' its found files, but my point is that on DOS/Windows, every
> command has to explicitly support subdirectories. If, instead, the
> 'find' command has to explicitly support everything you might want to
> do to files, that's even worse! So we need an execution form...
>
>> If you require a particular feature of 'ls', or any other command, you
>> can ask 'find' to invoke it directly (not via a shell):
>>
>>     find some_directory -name '*.pyc' -exec ls -l {} \;
>
> ... which this looks like, but it's not equivalent.

> That will execute
> 'ls -l' once for each file. You can tell, because the columns aren't
> aligned; for anything more complicated than simply 'ls -l', you
> potentially destroy any chance at bulk operations.

Thanks for elaborating that point. But still ...

> equivalent it *must* pass all the args to a single invocation of the
> program. You need to instead use xargs if you want it to be
> equivalent, and it's now getting to be quite an incantation:
>
> find some_directory -name \*.pyc -print0|xargs -0 ls -l
>
> And *that* is equivalent to the original, but it's way *way* longer
> and less convenient, which was my point.

If you are not already aware, it might interest you that 'find' in
(GNU findutils) 4.4.2. has

 -- Action: -execdir command {} +
     This works as for `-execdir command ;', except that the `{}' at
     the end of the command is expanded to a list of names of matching
     files.  This expansion is done in such a way as to avoid exceeding
     the maximum command line length available on the system.  Only one
     `{}' is allowed within the command, and it must appear at the end,
     immediately before the `+'.  A `+' appearing in any position other
     than immediately after `{}' is not considered to be special (that
     is, it does not terminate the command).

I believe that achieves the goal, without involving the shell.

It also has an -exec equivalent that works the same but has an
unrelated security issue and not recommended.

But if that '+' instead of ';' feature is not available on the
target system, then as far as I am aware it would be necessary
to use xargs as you say.

Anyway, the two points I wished to contribute are:

1) It is preferable to avoid shell command substitutions (the
backticks in the first example) and expansions where possible.

2) My observations on 'find' syntax, for anyone interested.

Cheers,
David
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to