From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8381 invoked by alias); 1 Jan 2014 21:45:47 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 18264 Received: (qmail 29549 invoked from network); 1 Jan 2014 21:45:40 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 From: Bart Schaefer Message-id: <140101134459.ZM8931@torch.brasslantern.com> Date: Wed, 01 Jan 2014 13:44:59 -0800 In-reply-to: Comments: In reply to zzapper "difference between ~ & ^ negation" (Jan 1, 3:28pm) References: X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-users@zsh.org Subject: Re: difference between ~ & ^ negation MIME-version: 1.0 Content-type: text/plain; charset=us-ascii On Jan 1, 3:28pm, zzapper wrote: > > What are the advantages/differences between the two types of "ignore" ^ ~ The ^ operator is similar to *~ except that it has high precedence, so the pattern following ^ (up to a slash) is excluded from the set of all files in the same level of directory hierarchy; e.g. foo/^bar/baz looks for baz in any subdirectory of foo except the subdirectory named bar. Therefore the pattern may not contain a slash. The ~ operator is very low precedence, so the entire directory search (including descent into subdirectories) to the left of the tilde is performed, and the pattern to the right of the tilde is tested against each file or directory to exclude it from the final result. This means that the pattern to the right of the tilde is not actually a glob; a wildcard in that pattern can match a slash in the tested name, and the pattern may contain slashes. Thus X~Z is nearly equivalent to X(e:'[[ $REPLY == Z ]] && reply=():'). To see advantages and disadvantages, consider two of your examples: > ls -lt **/*~*vssver.scc(.om[1,20]) # excluding vssver.scc > ls -lt **/^vssver.scc(.om[1,20]) # excluding vssver.scc (simpler) As you pointed out, the second case is simpler. However, these are not quite equivalent; the first one should be: ls -lt **/*~*/vssver.scc(.om[1,20]) Otherwise you also ignore "OLDvssver.scc" (for example), so the second case is also easier to use correctly. I find the most difficult thing to remember about ~ is that actual globbing happens only on the left, so the right side has to match the path names as simple strings. On the other hand, suppose you want to ignore vssver.scc only in the myproject subdirectory, but include it everywhere else: ls -lt **/*~*/myproject/vssver.scc There's no way to express this with the ^ operator except by using two globs and a qualifier: ls -lt **/^vssver.scc **/^myproject/vssver.scc(N) (The qualifier avoids a "no match" error if there is no vssver.scc file anywhere outside of myproject.) Now suppose you want everything that's neither in myproject nor named vssver.scc; these should all be equivalent: ls -lt **/^myproject/^vssver.scc ls -lt **/*~*/(myproject/*|vssver.scc) ls -lt **/^vssver.scc~*/myproject/* But these next two are not, do you see why? ls -lt **/^myproject~*/vssver.scc ls -lt **/^myproject/*~*/vssver.scc Important note: ^ is special only in cases where / is special (globs).