Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: /proc slows % echo /**/*/etc/r*(/N)



On Sun, Jan 21, 2024 at 9:19 AM Ray Andrews <rayandrews@xxxxxxxxxxx> wrote:
>
> I used to do this kind of thing without any problems:
>
>      % echo /**/*/etc/r*(/N)
>
> ... but just trying it, zsh labors for close to an hour, then spits out
> countless pages of:
>
> /proc/9/root/etc/rc0.d /proc/9/root/etc/rc1.d /proc/9/root/etc/rc2.d

Why /**/*/ rather than just /**/ ?  The extra /*/ there will expand
symbolic links, which are normally skipped by /**/.  It's not
otherwise adding anything to the traversal.

/proc/9 is for PID 9 and /proc/9/root is a symbolic link to the root
directory for that process, so by expanding that you're traversing the
whole filesystem again, which takes you back to /proc/ again, and so
on for every PID until zsh gives up (probably because it can't
allocate any more memory).

> ... I'm wondering why /proc wasn't a problem previously

I suspect previously you weren't adding that extra /*/.  What do you
mean for that to accomplish?

> and if there's
> anything I can do to filter it out of the search -- probably all the
> Linux 'system' directories too.  I recall that there's some test,
> something in permissions, some flag -- that identifies these
> not-quite-real directories -- zsh knows who they are.

There's no glob qualifier for that, if that's what you mean.  As it
happens, those directories always appear to be empty, so you can find
them with /*(/L0) but you can't use glob qualifiers in the middle of a
longer pattern (only at the end) so that won't help with your
recursive search.

> I know the tilde is used to make exceptions:
> but I can't get the syntax correct with the above.

That syntax is applied as a string match after the glob has already
expanded, so putting it at the end like this ...

>      % echo /**/*/etc/r*~/proc*(/N)

... is just going to waste even more time.

As Mark suggested, there are exclusion patterns you can apply, but
/**/ is still going to search the whole filesystem at least once,
possibly crossing mount points into other filesystems if you have
anything NFS or similarly remote mounted.

Without trying it, which I'm not going to do, I think the answer to
your specific question might be:

echo /**/^(proc|sys)/etc/r*(N)

But that might actually miss /etc/r* because it would be looking for
/etc/etc/.  There's no syntax for excluding things specifically from
the ** pattern.




Messages sorted by: Reverse Date, Date, Thread, Author