zsh-users
 help / color / mirror / code / Atom feed
* Filtering an array
@ 2012-02-24  7:11 Jesper Nygårds
  2012-02-24 10:25 ` Felix Herrmann
  2012-02-28  7:24 ` S. Cowles
  0 siblings, 2 replies; 4+ messages in thread
From: Jesper Nygårds @ 2012-02-24  7:11 UTC (permalink / raw)
  To: zsh-users

I am scratching my head over getting something seemingly simple to work.

I have written this function:

findfiles() {
    local myfiles myarg
    myfiles=( **/*$1* )
    shift
    for myarg in $@; do
        myfiles=${(M)myfiles:#*$myarg*}
    done
    print $myfiles
}

The idea is to find all files that contain all of the strings given. I
first find all files containing the first argument, then shift away
the first argument and filter the array of file names with each of the
remaining arguments.

However, for some reason only the first round of filtering (i.e. using
the second argument) is happening, as exemplified by the following
session:


% ls
a  ab  abc  ac  b  bc  c
% findfiles a b
ab abc
% findfiles a b c
ab abc
% findfiles a c
abc ac
% findfiles a c b
abc ac

I would expect both "findfiles a b c" and "findfiles a c b" to only
return "abc", but for some reason the third argument to the function
is not considered.

Can anyone help me sort this out?


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Filtering an array
  2012-02-24  7:11 Filtering an array Jesper Nygårds
@ 2012-02-24 10:25 ` Felix Herrmann
  2012-02-28  7:24 ` S. Cowles
  1 sibling, 0 replies; 4+ messages in thread
From: Felix Herrmann @ 2012-02-24 10:25 UTC (permalink / raw)
  To: zsh-users

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1193 bytes --]

Hi :)

On Fri, 24 Feb 2012 08:11:29 +0100, Jesper Nygårds wrote:
> The idea is to find all files that contain all of the strings given. I
> first find all files containing the first argument, then shift away
> the first argument and filter the array of file names with each of the
> remaining arguments.
> 
> However, for some reason only the first round of filtering (i.e. using
> the second argument) is happening[...].

I'm no expert at all at zsh-scripts but I think the problem is that
myfiles isn't an array anymore after the first iteration. I changed your
code to the following:

findfiles() {
    local myfiles myarg
    myfiles=( **/*$1* )
    shift
    for myarg; do
        myfiles=(${(M)myfiles:#*$myarg*})
    done
    print $myfiles
}

There are two little differences here. First of all, I didn't write '$@'
in the for-line. If you don't give an 'in x', for iterates over the
remaining arguments.

The second difference - and the more important one - is, that I put ()
around the rhs of the myfiles-assignment, to make sure to assign an
array to the variable myfiles. I think that was the catch. After this
modification, your script works fine :)

Greetings,
Felix Herrmann.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Filtering an array
  2012-02-24  7:11 Filtering an array Jesper Nygårds
  2012-02-24 10:25 ` Felix Herrmann
@ 2012-02-28  7:24 ` S. Cowles
  2012-02-29 13:43   ` Jesper Nygårds
  1 sibling, 1 reply; 4+ messages in thread
From: S. Cowles @ 2012-02-28  7:24 UTC (permalink / raw)
  To: Jesper Nygårds; +Cc: zsh-users

[-- Attachment #1: Type: TEXT/PLAIN, Size: 2002 bytes --]

On Fri, 24 Feb 2012, Jesper Nygårds wrote:
> Date: Thu, 23 Feb 2012 23:11:29
> From: Jesper Nygårds <jesper.nygards@gmail.com>
> To: zsh-users@zsh.org
> Subject: Filtering an array
>
> I am scratching my head over getting something seemingly simple to work.
>
> I have written this function:
>
> findfiles() {
>    local myfiles myarg
>    myfiles=( **/*$1* )
>    shift
>    for myarg in $@; do
>        myfiles=${(M)myfiles:#*$myarg*}
>    done
>    print $myfiles
> }

jesper

this is my version of your function.  the biggest difference i see
between your function and my version (with regard to intent and
disregarding coding errors), is the initial expansion of ${myfiles}.
file selection in both versions is done by pattern matching, so i
did not use the same initial file list loading as yours

 	myfiles=( **/*$1* )

to cause any subsetting; that step struck me as unneccessary.

also, your version redefines ${myfiles} in every instance of the for
loop; this never accummulates the pattern matches which is what i
thought was your objective.

if i misunderstood your requirements, i apologize.

the function shown here does give a correct list of unique files
matching the pattern[s] given on the invocation line.

usage:
 	findfiles starting_sub_dir pat1 [pat2...]

findfiles(){
 	# parameter declarations.
 	typeset -a pats allfiles
 	typeset -aU selection
 	local srcdir pat
 	# argument parsing and checking.
 	srcdir=${1}
 	if [[ ! -d ${srcdir} ]]
 	then
 		# bomb.
 		return 1
 	fi
 	shift
 	# patterns for which to search.
 	pats=( $@ )
 	# get all files (only files, including dot files) in specified
 	# source directory.
 	allfiles=( ${srcdir}/**/*(D,.) )
 	# initialize the collection.
 	selection=()
 	# do the subsetting and collecting.
 	for pat in ${pats}
 	do
 		selection=(
 			${selection}
 			# append any additional matches.
 			${(M)allfiles:#*${pat}*}
 		)
 	done
 	# report the results.
 	print -l ${selection}
 	# clean up.
 	unset srcdir pat pats allfiles selection
}

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Filtering an array
  2012-02-28  7:24 ` S. Cowles
@ 2012-02-29 13:43   ` Jesper Nygårds
  0 siblings, 0 replies; 4+ messages in thread
From: Jesper Nygårds @ 2012-02-29 13:43 UTC (permalink / raw)
  To: zsh-users

2012/2/28 S. Cowles <scowles@ckhb.org>:
> this is my version of your function.

Thanks for sharing this; it contains many useful idioms that I will
incorporate into my own solution.

However, if I read it correctly, your solution solves a different
problem than the one I was trying to solve: you version lists all
files that match ANY of the given patterns, whereas my intent was to
only list files which matches ALL of the given patterns. That's the
reason for my cumulative filtering of the results in myfiles.

Thanks again,

Jesper


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-02-29 14:10 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-24  7:11 Filtering an array Jesper Nygårds
2012-02-24 10:25 ` Felix Herrmann
2012-02-28  7:24 ` S. Cowles
2012-02-29 13:43   ` Jesper Nygårds

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).