[comp.unix.questions] Idiom for $

das@lanai.cs.ucla.edu (03/18/89)

Do you have a favorite idiom for (ksh syntax):
	$(ls -d $pattern 2>/dev/null)
that does not involve invocation of a separate process and is not aesthetically
unpleasant?  The intent is that if any filenames match the pattern, then use
them; otherwise, use the null string.  This shows up when you want to say
	for f in *
(Which is not what you really want, since if the directory is empty, f takes on
the value "*").

-- David Smallberg, das@cs.ucla.edu, ...!{uunet,ucbvax,rutgers}!cs.ucla.edu!das

maart@cs.vu.nl (Maarten Litmaath) (03/21/89)

das@lanai.cs.ucla.edu writes:

\Do you have a favorite idiom for (ksh syntax):
\	for f in *
\(Which is not what you really want, since if the directory is empty, f takes on
\the value "*").

set - `
	for i in .* *
	do
		echo "$i"
	done | sed -e '/^\.$/d' -e '/^\.\.$/d'
`
[ -f "$1" ] && {
	for i
	do
		echo "$i"
	done
}
-- 
 Modeless editors and strong typing:   |Maarten Litmaath @ VU Amsterdam:
   both for people with weak memories. |maart@cs.vu.nl, mcvax!botter!maart

leo@philmds.UUCP (Leo de Wit) (03/23/89)

In article <2189@solo11.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
|das@lanai.cs.ucla.edu writes:
|
|\Do you have a favorite idiom for (ksh syntax):
|\	for f in *
|\(Which is not what you really want, since if the directory is empty, f takes on
|\the value "*").
|
|set - `
|	for i in .* *
|	do
|		echo "$i"
|	done | sed -e '/^\.$/d' -e '/^\.\.$/d'
|`
|[ -f "$1" ] && {
|	for i
|	do
|		echo "$i"
|	done
|}

Yes, but the guy also said:
|that does not involve invocation of a separate process and is not aesthetically
|unpleasant?  The intent is that if any filenames match the pattern, then use
|them; otherwise, use the null string.

Your solution needs several addition process invocations (especially
when 'echo' is not a shell builtin). It selects 'all files in current
directory' instead of those matching $pattern (though that can easily
be fixed).

Alternative that uses only builtins:

set - $pattern             # expand into $*

case $# in
1)  p1="$1"                # one arg only; could be mismatch.
    set - $pattern?*       # retry with other pattern (one char extra).
    n2=$#                  # save number of matches.
    set - $pattern*        # retry with yet another pattern.
    case $# in             # 1 <= $n2 <= $# holds now.
    1)   case $1 in
         "$p1") : ;;       # valid match on $p1.
         *)     shift;;    # no match; empty $*.
         esac;;
    $n2) set ""; shift;;   # matches for $pattern* == # matches for $pattern?*,
                           #     so no match on $p1; empty $*.
    *)   set "$p1";;       # $# > n2 so there was a valid match on $p1.
    esac;;
esac

and now you can use $* as the list of files; it is empty if there was
no match. You might want to convert this into a ksh function (I'm not
familiar with this shell).

    Leo.