Re: shell commands - exclusion

2009-02-08 Thread Jonathan McKeown
On Friday 06 February 2009 02:55, Chris Whitehouse wrote:

 I think you should be able to do it with a combination of -prune and
 -delete (or -exec rm -rf {} \; ) on a find command. Substitute your
 other commands for rm -rf in the -exec above.

 I would give you a working example except I can't figure out the syntax
 for -prune. Examples from google don't seem to work in (my) FreeBSD.

[skip to the end for a simple answer without the lengthy exposition]

find(1) can be confusing, especially if you think of the ``actions'' 
( -print, -exec and -delete plus their variants like -ls and -ok ) as 
something different from the ``tests'' ( -name and so on), or if you don't 
take account of the evaluation order.

A find expression comprises a number of what the manpage calls primaries, each 
of which evaluates as true or false. (It may also have a side-effect, 
like -print whose side-effect is to print the name). Primaries can be 
combined with -and (which is usually implied) or -or. Where -and and -or both 
occur, find will group the -anded primaries together before evaluation. 
Taking one of your examples below,

find . -print -or -prune -name dir1

this is grouped as

find . -print -or \( -prune -and -name dir1 \)

find will then evaluate the whole expression from left to right for each 
pathname in the tree it's looking at, stopping within each set of (implied) 
parentheses and within the overall expression as soon as it can determine 
truth or falsehood. (This is what's referred to in programming as 
short-circuiting in boolean expressions).

If primaries are linked by -and, find can stop at the first one that's false, 
knowing the expression is false; if they're linked by -or it can stop at the 
first one that's true, knowing the expression is true. Otherwise it has to 
evaluate the whole expression.

Before it does this, though, find checks for side-effects. If there isn't a 
side-effect anywhere in your expression, find will put brackets round the 
whole expression and a -print after it.

Looking at your examples:

 chr...@pcbsd% find .

(No expression). Find adds a -print, so this is the same as the next one:

 chr...@pcbsd% find . -print
 .
 ./test.mov
 ./test.mpg
 ./dir1
 ./dir1/file1
 ./dir1/file2
 ./file3

-print is always true so the expression is true for each name - they get 
printed as a side-effect.

 chr...@pcbsd% find . -print -o -prune dir1
 find: dir1: unknown option

-prune doesn't take an argument, so dir1 is a syntax error.

 chr...@pcbsd% find . -print -o -prune -name dir1

find evaluates the print, which prints each name as its side-effect. -print 
evaluates as true. Since it's in an -or, find can stop there, so it never 
sees the second expression ( -prune -and -name dir1: the -and is implicit).
 .
 ./test.mov
 ./test.mpg
 ./dir1
 ./dir1/file1
 ./dir1/file2
 ./file3

 chr...@pcbsd% find . -print -o -name dir1 -prune

Same again: find stops after the -print which is always true, and ignores 
the -name dir1 -and -prune.

 chr...@pcbsd% find . -name * -o -name dir1 -prune

None of these primaries has a side-effect, so find rewrites this internally as

find . \( -name * -or -name dir1 -prune \) -print

-name * is always true, so find can ignore everything after the -or up to 
the parenthesis. Because the first expression is true, and the parens are 
followed by (an implied) -and, find has to evaluate the -print, which is 
always true, so the whole expression is always true and it always prints the 
name as a side-effect.
 .
 ./test.mov
 ./test.mpg
 ./dir1
 ./dir1/file1
 ./dir1/file2
 ./file3

What you need is an expression with two outcomes: a -prune for some names and 
a -print for others. That tells you you need an -or, and the -print must come 
after it because it's always true. Before the -or, -prune is always true so 
you need some sort of testing primary before the -prune.

That gives you

find . -name dir1 -prune -or -print

Jonathan
___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org


Re: shell commands - exclusion

2009-02-08 Thread Chris Whitehouse

Jonathan McKeown wrote:

On Friday 06 February 2009 02:55, Chris Whitehouse wrote:

I think you should be able to do it with a combination of -prune and
-delete (or -exec rm -rf {} \; ) on a find command. Substitute your
other commands for rm -rf in the -exec above.

I would give you a working example except I can't figure out the syntax
for -prune. Examples from google don't seem to work in (my) FreeBSD.


[skip to the end for a simple answer without the lengthy exposition]

find(1) can be confusing, especially if you think of the ``actions'' 
( -print, -exec and -delete plus their variants like -ls and -ok ) as 
something different from the ``tests'' ( -name and so on), or if you don't 
take account of the evaluation order.


A find expression comprises a number of what the manpage calls primaries, each 
of which evaluates as true or false. (It may also have a side-effect, 
like -print whose side-effect is to print the name). Primaries can be 
combined with -and (which is usually implied) or -or. Where -and and -or both 
occur, find will group the -anded primaries together before evaluation. 
Taking one of your examples below,


find . -print -or -prune -name dir1

this is grouped as

find . -print -or \( -prune -and -name dir1 \)

find will then evaluate the whole expression from left to right for each 
pathname in the tree it's looking at, stopping within each set of (implied) 
parentheses and within the overall expression as soon as it can determine 
truth or falsehood. (This is what's referred to in programming as 
short-circuiting in boolean expressions).


If primaries are linked by -and, find can stop at the first one that's false, 
knowing the expression is false; if they're linked by -or it can stop at the 
first one that's true, knowing the expression is true. Otherwise it has to 
evaluate the whole expression.


Before it does this, though, find checks for side-effects. If there isn't a 
side-effect anywhere in your expression, find will put brackets round the 
whole expression and a -print after it.


Looking at your examples:


chr...@pcbsd% find .


(No expression). Find adds a -print, so this is the same as the next one:


chr...@pcbsd% find . -print
.
./test.mov
./test.mpg
./dir1
./dir1/file1
./dir1/file2
./file3


-print is always true so the expression is true for each name - they get 
printed as a side-effect.



chr...@pcbsd% find . -print -o -prune dir1
find: dir1: unknown option


-prune doesn't take an argument, so dir1 is a syntax error.


chr...@pcbsd% find . -print -o -prune -name dir1


find evaluates the print, which prints each name as its side-effect. -print 
evaluates as true. Since it's in an -or, find can stop there, so it never 
sees the second expression ( -prune -and -name dir1: the -and is implicit).

.
./test.mov
./test.mpg
./dir1
./dir1/file1
./dir1/file2
./file3



chr...@pcbsd% find . -print -o -name dir1 -prune


Same again: find stops after the -print which is always true, and ignores 
the -name dir1 -and -prune.



chr...@pcbsd% find . -name * -o -name dir1 -prune


None of these primaries has a side-effect, so find rewrites this internally as

find . \( -name * -or -name dir1 -prune \) -print

-name * is always true, so find can ignore everything after the -or up to 
the parenthesis. Because the first expression is true, and the parens are 
followed by (an implied) -and, find has to evaluate the -print, which is 
always true, so the whole expression is always true and it always prints the 
name as a side-effect.

.
./test.mov
./test.mpg
./dir1
./dir1/file1
./dir1/file2
./file3


What you need is an expression with two outcomes: a -prune for some names and 
a -print for others. That tells you you need an -or, and the -print must come 
after it because it's always true. Before the -or, -prune is always true so 
you need some sort of testing primary before the -prune.


That gives you

find . -name dir1 -prune -or -print

Jonathan
___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org

Thank you for this excellent answer! Now reading the man page begins to 
make sense.


Chris
___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org


Re: shell commands - exclusion

2009-02-05 Thread Chris Whitehouse

Jaime wrote:

On Wed, Feb 4, 2009 at 9:35 AM, t-u-t marshc...@gmail.com wrote:
if i have say one (or even two) single file/directories among many others,
and i want to perform any said function like cp, mv, rm, etc.. , to all
other files except that one or two, is there a way to do that in a single
command?
e.g
rm -r * {-except foo1 foo15}


I think you should be able to do it with a combination of -prune and 
-delete (or -exec rm -rf {} \; ) on a find command. Substitute your 
other commands for rm -rf in the -exec above.


I would give you a working example except I can't figure out the syntax 
for -prune. Examples from google don't seem to work in (my) FreeBSD.


chr...@pcbsd% find .
.
./test.mov
./test.mpg
./dir1
./dir1/file1
./dir1/file2
./file3
chr...@pcbsd% find . -print
.
./test.mov
./test.mpg
./dir1
./dir1/file1
./dir1/file2
./file3
chr...@pcbsd% find . -print -o -prune dir1
find: dir1: unknown option
chr...@pcbsd% find . -print -o -prune -name dir1
.
./test.mov
./test.mpg
./dir1
./dir1/file1
./dir1/file2
./file3
chr...@pcbsd% find . -print -o -name dir1 -prune
.
./test.mov
./test.mpg
./dir1
./dir1/file1
./dir1/file2
./file3
chr...@pcbsd% find . -o -name dir1 -prune
find: -o: no expression before -o
chr...@pcbsd% find . -name * -o -name dir1 -prune
.
./test.mov
./test.mpg
./dir1
./dir1/file1
./dir1/file2
./file3
chr...@pcbsd%

(Please don't tell me to read the man page, I have several times. Even 
Aeleen Frisch says it is impenetrable :P)


Chris
___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org


Re: shell commands - exclusion

2009-02-05 Thread Paul Procacci

Chris Whitehouse wrote:

Jaime wrote:

On Wed, Feb 4, 2009 at 9:35 AM, t-u-t marshc...@gmail.com wrote:
if i have say one (or even two) single file/directories among many 
others,

and i want to perform any said function like cp, mv, rm, etc.. , to all
other files except that one or two, is there a way to do that in a 
single

command?
e.g
rm -r * {-except foo1 foo15}


I think you should be able to do it with a combination of -prune and 
-delete (or -exec rm -rf {} \; ) on a find command. Substitute your 
other commands for rm -rf in the -exec above.


I would give you a working example except I can't figure out the 
syntax for -prune. Examples from google don't seem to work in (my) 
FreeBSD.


chr...@pcbsd% find .
..
../test.mov
../test.mpg
../dir1
../dir1/file1
../dir1/file2
../file3
chr...@pcbsd% find . -print
..
../test.mov
../test.mpg
../dir1
../dir1/file1
../dir1/file2
../file3
chr...@pcbsd% find . -print -o -prune dir1
find: dir1: unknown option
chr...@pcbsd% find . -print -o -prune -name dir1
..
../test.mov
../test.mpg
../dir1
../dir1/file1
../dir1/file2
../file3
chr...@pcbsd% find . -print -o -name dir1 -prune
..
../test.mov
../test.mpg
../dir1
../dir1/file1
../dir1/file2
../file3
chr...@pcbsd% find . -o -name dir1 -prune
find: -o: no expression before -o
chr...@pcbsd% find . -name * -o -name dir1 -prune
..
../test.mov
../test.mpg
../dir1
../dir1/file1
../dir1/file2
../file3
chr...@pcbsd%

(Please don't tell me to read the man page, I have several times. Even 
Aeleen Frisch says it is impenetrable :P)


Chris
___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to 
freebsd-questions-unsubscr...@freebsd.org


find . \! -name blah -a \! -name blah2 -delete

no?
___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org


Re: shell commands - exclusion

2009-02-04 Thread Lars Eighner

On Wed, 4 Feb 2009, t-u-t wrote:


hi, i don't know if this is a freak question, but i was looking around to
see if this is possible, and what the convention would be.

if i have say one (or even two) single file/directories among many others,
and i want to perform any said function like cp, mv, rm, etc.. , to all
other files except that one or two, is there a way to do that in a single
command?
e.g
rm -r * {-except foo1 foo15}


In general this is not possible.  A few commands have exclusion options, but
not many.  Some shells have ways of managing glob exclusion (it's the shell
that expands wildcard patterns).  Setting GLOBIGNORE works in BASH, whether
something similar works in others, you will have to investigate yourself. 
But that isn't one line as you have to set GLOBIGNORE.  BASH also has an

extended pattern matching option which includes negation, so you might want
to look into that.


and if there is, could the same be applied to other similar batch (?)
operations, like pkg_delete -f * { except firefox3 wine thunderbird }
etc..


pkg_delete can take regular expression arguments (see -x).  Perhaps you
can devise one that will do the trick.  Beware, however: it can take
multiple regular expressions and deletes package which match ANY (not all)
of them.


i'm a bit new to the shell (took me a while to figure out *ls* and *ls |
more*), but i can't find anything from google cuz i don't know what this
would be called in the first place.


Shell globbing is the operation by which the shell expands wildcards and
finds matches.  What you want to do exclude things from shell globbing.


otherwise is it better to protect them with chflags or other trickery?


watch out anything involving recursion --- things can happen that you don't
expect unless you really know what you are doing.

--
Lars Eighner
http://www.larseighner.com/index.html
8800 N IH35 APT 1191 AUSTIN TX 78753-5266

___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org


Re: shell commands - exclusion

2009-02-04 Thread Dan Nelson
In the last episode (Feb 04), t-u-t said:
 hi, i don't know if this is a freak question, but i was looking around to
 see if this is possible, and what the convention would be.
 
 if i have say one (or even two) single file/directories among many others,
 and i want to perform any said function like cp, mv, rm, etc..  , to all
 other files except that one or two, is there a way to do that in a single
 command?
 e.g
 rm -r * {-except foo1 foo15}

zsh has the ^ and ~ glob metacharacters that are enabled with you enable
EXTENDED_GLOB:

   ^x (Requires EXTENDED_GLOB to be set.)  Matches anything except
  the pattern x.  This has a higher precedence than `/', so
  `^foo/bar' will search directories in `.' except `./foo' for a
  file named `bar'.

   x~y(Requires EXTENDED_GLOB to be set.)  Match anything that
  matches the pattern x but does not match y.  This has lower
  precedence than any operator except `|', so `*/*~foo/bar' will
  search for all files in all directories in `.' and then
  exclude `foo/bar' if there was such a match.  Multiple
  patterns can be excluded by `foo~bar~baz'.  In the exclusion
  pattern (y), `/' and `.' are not treated specially the way
  they usually are in globbing.
 
 and if there is, could the same be applied to other similar batch (?)
 operations, like pkg_delete -f * { except firefox3 wine thunderbird }
 etc..

That wildcard is expanded internally by pkg_delete using the C fnmatch()
function, which just does simple *?[] shell pattern matching.
 
 i'm a bit new to the shell (took me a while to figure out *ls* and *ls |
 more*), but i can't find anything from google cuz i don't know what this
 would be called in the first place.
 
 otherwise is it better to protect them with chflags or other trickery?

One workaround is to temporarily move the files you don't want to process
into another directory, then move them back when you're done.

-- 
Dan Nelson
dnel...@allantgroup.com
___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org


Re: shell commands - exclusion

2009-02-04 Thread t-u-t
On Wed, Feb 4, 2009 at 4:26 PM, Lars Eighner luvbeas...@larseighner.comwrote:


 In general this is not possible.  A few commands have exclusion options,
 but
 not many.  Some shells have ways of managing glob exclusion (it's the shell
 that expands wildcard patterns).  Setting GLOBIGNORE works in BASH, whether
 something similar works in others, you will have to investigate yourself.
 But that isn't one line as you have to set GLOBIGNORE.  BASH also has an
 extended pattern matching option which includes negation, so you might want
 to look into that.
 pkg_delete can take regular expression arguments (see -x).  Perhaps you
 can devise one that will do the trick.  Beware, however: it can take
 multiple regular expressions and deletes package which match ANY (not all)
 of them.
 Shell globbing is the operation by which the shell expands wildcards and
 finds matches.  What you want to do exclude things from shell globbing.
 watch out anything involving recursion --- things can happen that you don't
 expect unless you really know what you are doing.


thank you,
i can keep to regular painstaking methods for now, but would like to get the
hang of it in future;. knowing what i'm looking for now is a big step for
me.
thanks again
___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org


Re: shell commands - exclusion

2009-02-04 Thread t-u-t
On Wed, Feb 4, 2009 at 4:48 PM, Dan Nelson dnel...@allantgroup.com wrote:

 zsh has the ^ and ~ glob metacharacters that are enabled with you enable
 EXTENDED_GLOB:

   ^x (Requires EXTENDED_GLOB to be set.)  Matches anything except
  the pattern x.  This has a higher precedence than `/', so
  `^foo/bar' will search directories in `.' except `./foo' for a
  file named `bar'.

   x~y(Requires EXTENDED_GLOB to be set.)  Match anything that
  matches the pattern x but does not match y.  This has lower
  precedence than any operator except `|', so `*/*~foo/bar' will
  search for all files in all directories in `.' and then
  exclude `foo/bar' if there was such a match.  Multiple
  patterns can be excluded by `foo~bar~baz'.  In the exclusion
  pattern (y), `/' and `.' are not treated specially the way
  they usually are in globbing.

  and if there is, could the same be applied to other similar batch (?)
  operations, like pkg_delete -f * { except firefox3 wine thunderbird }
  etc..

 That wildcard is expanded internally by pkg_delete using the C fnmatch()
 function, which just does simple *?[] shell pattern matching.

  i'm a bit new to the shell (took me a while to figure out *ls* and *ls |
  more*), but i can't find anything from google cuz i don't know what this
  would be called in the first place.
 
  otherwise is it better to protect them with chflags or other trickery?

 One workaround is to temporarily move the files you don't want to process
 into another directory, then move them back when you're done.

 --

thank you,
i am interested in knowing how to do this stuff in general for simple
operations, since like this workaround would work fine with file
operations, but not for pkg_delete and other commands i can't think of right
now. I was just wondering if there was a commonly used/known method or
*switch* i could look into.

however, form this post i get the impression that it is better( and
worthwhile) to learn to do some proper scripting. say, prepare a list in a
file, then pass each one to the command instead of *.

cheers
___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org


Re: shell commands - exclusion

2009-02-04 Thread Roland Smith
On Wed, Feb 04, 2009 at 03:35:52PM +0100, t-u-t wrote:
 hi, i don't know if this is a freak question, but i was looking around to
 see if this is possible, and what the convention would be.
 
 if i have say one (or even two) single file/directories among many others,
 and i want to perform any said function like cp, mv, rm, etc.. , to all
 other files except that one or two, is there a way to do that in a single
 command?
 e.g
 rm -r * {-except foo1 foo15}

The easiest way would be to move the few files/directories you don't
want to include in your command out of the way first. :-)

 and if there is, could the same be applied to other similar batch (?)
 operations, like pkg_delete -f * { except firefox3 wine thunderbird }
 etc..
I don't think so.

If the couple of files you don't want to rm/whatever you could try using
the find(1) command to get all the other files. The find command is a
very good tool to know.

 i'm a bit new to the shell (took me a while to figure out *ls* and *ls |
 more*), but i can't find anything from google cuz i don't know what this
 would be called in the first place.

Maybe a stupid question, but do you know how to read manual pages?
E.g. for 'find', just enter the command 'man find' in your shell.

 otherwise is it better to protect them with chflags or other trickery?

That would be my other suggestion.

Roland
-- 
R.F.Smith   http://www.xs4all.nl/~rsmith/
[plain text _non-HTML_ PGP/GnuPG encrypted/signed email much appreciated]
pgp: 1A2B 477F 9970 BA3C 2914  B7CE 1277 EFB0 C321 A725 (KeyID: C321A725)


pgpBb0RvKa0Bk.pgp
Description: PGP signature


Re: shell commands - exclusion

2009-02-04 Thread Jaime
On Wed, Feb 4, 2009 at 9:35 AM, t-u-t marshc...@gmail.com wrote:
 if i have say one (or even two) single file/directories among many others,
 and i want to perform any said function like cp, mv, rm, etc.. , to all
 other files except that one or two, is there a way to do that in a single
 command?
 e.g
 rm -r * {-except foo1 foo15}

I'm just shooting in the dark here, but what about this?

ls | grep -v foo1 | grep -v foo15 | xargs rm -rf

Remember the Unix pipe and the grep and xargs commands.  It can
solve a lot of things by stringing together a lot of smaller commands.
 I think that this might be one of those situations.

Good luck,
Jaime


-- 
To affect the quality of the day, that is the highest of arts.  --
Henry David Thoreau

Tone of voice in email is misunderstood 50% of the time.
Source:  http://www.howtoweb.com/cgi-bin/insider.pl?zone=214061
___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org


Re: shell commands - exclusion

2009-02-04 Thread William Gordon Rutherdale

Lars Eighner wrote:

On Wed, 4 Feb 2009, t-u-t wrote:

hi, i don't know if this is a freak question, but i was looking 
around to

see if this is possible, and what the convention would be.

if i have say one (or even two) single file/directories among many 
others,

and i want to perform any said function like cp, mv, rm, etc.. , to all
other files except that one or two, is there a way to do that in a 
single

command?
e.g
rm -r * {-except foo1 foo15}


In general this is not possible. . . .
Oh yes it is, it is very easy.  I've done things like this in unix 
environments for years.  I also apply it to tar commands all the time.


All you have to do is this:

$ ls rm.in
$ vi rm.in
  . . . edit out all the files you don't want to erase . . .
$ rm `cat rm.in`

-Will


___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to freebsd-questions-unsubscr...@freebsd.org