Re: shell commands - exclusion
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
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
On Wed, Feb 4, 2009 at 4:26 PM, Lars Eighner wrote: > > 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
On Wed, Feb 4, 2009 at 4:48 PM, Dan Nelson 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
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
On Wed, Feb 4, 2009 at 9:35 AM, t-u-t 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
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"
Re: shell commands - exclusion
Jaime wrote: On Wed, Feb 4, 2009 at 9:35 AM, t-u-t 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
Chris Whitehouse wrote: Jaime wrote: On Wed, Feb 4, 2009 at 9:35 AM, t-u-t 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
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
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"