Discussion:
Bash file "if exist" and looping question
(too old to reply)
Herb Martin
2005-07-06 03:44:55 UTC
Permalink
The following is a VERY naive way to accomplish "if any
files in a pattern exist" do some stuff with them.

Please suggest the best place to ask such questions, good
web sources for learning Linux/bash/etc scripting, and
how to do this 'right' (or at least better):

#!/usr/bin/sh
for A in /etc/mail/move/*; do
if [ -f ${A} ] ; then
echo Do something with $A
echo And: mv /etc/mail/move/* /etc/mail/oldspam/
fi
done
###############end##################


When I tried the (more) naive method of merly testing on
[ -f /etc/mail/move/* ] there were errors (only) when the files
existed.

FYI: This was run on Cygwin if it matters.
--
Herb Martin
Chris F.A. Johnson
2005-07-06 04:08:06 UTC
Permalink
Post by Herb Martin
The following is a VERY naive way to accomplish "if any
files in a pattern exist" do some stuff with them.
Please suggest the best place to ask such questions, good
web sources for learning Linux/bash/etc scripting, and
Try the comp.unix.shell newsgroup.
Post by Herb Martin
#!/usr/bin/sh
for A in /etc/mail/move/*; do
if [ -f ${A} ] ; then
echo Do something with $A
echo And: mv /etc/mail/move/* /etc/mail/oldspam/
fi
done
###############end##################
That is a good way to do it, but it could be a little faster like
this:

set -- /etc/mail/move/*
[ -f "$1" ] &&
for A
do
echo Do something with $A
echo And: mv /etc/mail/move/* /etc/mail/oldspam/
done
Post by Herb Martin
When I tried the (more) naive method of merly testing on
[ -f /etc/mail/move/* ] there were errors (only) when the files
existed.
That fails because the shell expands the wild card, and the
resulting command looks something like:

[ -f /etc/mail/move/abc /etc/mail/move/def /etc/mail/move/ghi ]

There can only be one argument to -f, so you get an error.
Post by Herb Martin
FYI: This was run on Cygwin if it matters.
--
Chris F.A. Johnson <http://cfaj.freeshell.org>
==================================================================
Shell Scripting Recipes: A Problem-Solution Approach, 2005, Apress
<http://www.torfree.net/~chris/books/cfaj/ssr.html>
Herb Martin
2005-07-06 05:43:16 UTC
Permalink
Post by Chris F.A. Johnson
Post by Herb Martin
The following is a VERY naive way to accomplish "if any
files in a pattern exist" do some stuff with them.
Please suggest the best place to ask such questions, good
web sources for learning Linux/bash/etc scripting, and
Try the comp.unix.shell newsgroup.
Thanks.
Post by Chris F.A. Johnson
Post by Herb Martin
#!/usr/bin/sh
for A in /etc/mail/move/*; do
if [ -f ${A} ] ; then
echo Do something with $A
echo And: mv /etc/mail/move/* /etc/mail/oldspam/
fi
done
###############end##################
That is a good way to do it, but it could be a little faster like
I wasn't worried much about speed but my method seemed incredibly
ugly -- and it would run slow if there were a thousand files since
the commands were going to operate on all files the first time and the
"for" was really gratuitious -- just a sneaky way to do something if
any existed.
Post by Chris F.A. Johnson
set -- /etc/mail/move/*
[ -f "$1" ] &&
for A
do
echo Do something with $A
echo And: mv /etc/mail/move/* /etc/mail/oldspam/
done
I don't understand the "set --" in this context nor how it
plays with the testing of -f but it looks simple enough....

Thanks again.

I found this free 600+ page tutorial:

http://www.tldp.org/LDP/abs/abs-guide.pdf
--
Herb Martin
Chris F.A. Johnson
2005-07-06 13:55:44 UTC
Permalink
Post by Herb Martin
Post by Chris F.A. Johnson
Post by Herb Martin
The following is a VERY naive way to accomplish "if any
files in a pattern exist" do some stuff with them.
[snip]
Post by Herb Martin
Post by Chris F.A. Johnson
Post by Herb Martin
#!/usr/bin/sh
for A in /etc/mail/move/*; do
if [ -f ${A} ] ; then
echo Do something with $A
echo And: mv /etc/mail/move/* /etc/mail/oldspam/
fi
done
###############end##################
That is a good way to do it, but it could be a little faster like
I wasn't worried much about speed but my method seemed incredibly
ugly -- and it would run slow if there were a thousand files since
the commands were going to operate on all files the first time and the
"for" was really gratuitious -- just a sneaky way to do something if
any existed.
It all depends on what you want to do with the files. If, for
example, you just want to move them, there's no need for a loop:

set -- /etc/mail/move/*
[ -f "$1" ] && mv /etc/mail/move/* /etc/mail/oldspam/


If you have to operate on each file individually, then you need
the loop.
Post by Herb Martin
Post by Chris F.A. Johnson
set -- /etc/mail/move/*
[ -f "$1" ] &&
for A
do
echo Do something with $A
echo And: mv /etc/mail/move/* /etc/mail/oldspam/
done
I don't understand the "set --" in this context nor how it
plays with the testing of -f but it looks simple enough....
See the last two sentences from "help set".
Post by Herb Martin
http://www.tldp.org/LDP/abs/abs-guide.pdf
I prefer the HTML version:

<http://www.tldp.org/LDP/abs/html/index.html>
--
Chris F.A. Johnson <http://cfaj.freeshell.org>
==================================================================
Shell Scripting Recipes: A Problem-Solution Approach, 2005, Apress
<http://www.torfree.net/~chris/books/cfaj/ssr.html>
Herb Martin
2005-07-06 18:26:16 UTC
Permalink
Post by Chris F.A. Johnson
It all depends on what you want to do with the files. If, for
set -- /etc/mail/move/*
[ -f "$1" ] && mv /etc/mail/move/* /etc/mail/oldspam/
If you have to operate on each file individually, then you need
the loop.
Right. The loop was the ugly kludge I introduced to test for the
existence of ANY file matching the pattern -- all of my actions
were possible on the WHOLE set at once (like move).

FYI: I was SpamAssassin "learning" (sa-learn) a directory of
files to either Ham or Spam, then moving them to an "old" (Ham
or Spam) directory afterwards.

The loop was 'stupid' -- but it was my method of checking for
existence -- and this was my reason for asking you for a better
way.

After you showed me the "set --" syntax I found that in one of
my books and have begun to understand it...

The loop is gone -- thanks, it works with the set --; [-f "$1"]
--
Herb Martin
Daniel Ganek
2005-07-07 14:42:48 UTC
Permalink
Post by Herb Martin
Post by Chris F.A. Johnson
It all depends on what you want to do with the files. If, for
set -- /etc/mail/move/*
[ -f "$1" ] && mv /etc/mail/move/* /etc/mail/oldspam/
If you have to operate on each file individually, then you need
the loop.
Right. The loop was the ugly kludge I introduced to test for the
existence of ANY file matching the pattern -- all of my actions
were possible on the WHOLE set at once (like move).
FYI: I was SpamAssassin "learning" (sa-learn) a directory of
files to either Ham or Spam, then moving them to an "old" (Ham
or Spam) directory afterwards.
The loop was 'stupid' -- but it was my method of checking for
existence -- and this was my reason for asking you for a better
way.
After you showed me the "set --" syntax I found that in one of
my books and have begun to understand it...
The loop is gone -- thanks, it works with the set --; [-f "$1"]
If all you're doing is moving every file in /etc/mail/move you really don't
need the test; e.g.,

mv /etc/mail/move/* /etc/mail/oldspam/ 2>/dev/null

/dan
Herb Martin
2005-07-07 15:18:39 UTC
Permalink
Post by Daniel Ganek
Post by Herb Martin
The loop is gone -- thanks, it works with the set --; [-f "$1"]
If all you're doing is moving every file in /etc/mail/move you really don't
need the test; e.g.,
mv /etc/mail/move/* /etc/mail/oldspam/ 2>/dev/null
I understand that but no, I was performing several commands
(each one operating on the entire file set) and two of these
commands had a relatively long startup time, so that I wanted
to skip the set entirely if there were 0 files to process.

Below is the actual final version (including my real paths which
weren't relevant to the original question):

#!/usr/bin/bash
for TYPE in spam ham; do
echo -n $TYPE...
set -- /etc/mail/spamassassin/$TYPE/move/*
[ -f "$1" ]
&& \
sa-learn --forget --showdots /etc/mail/spamassassin/$TYPE/move/* &&
\
sa-learn --$TYPE --showdots /etc/mail/spamassassin/$TYPE/move/* && \
mv /etc/mail/spamassassin/$TYPE/move/* /etc/mail/spamassassin/old$TYPE/
echo done.
done
exit 0


I have tools that move spam and ham messages into those ../$TYPE/move
directories and this process ensures the mail is properly classified by
SpamAssassin and then moved to the ./old$TYPE/ directory for archiving.

Thanks to everyone who responded.

--
Herb
William Park
2005-07-17 03:14:04 UTC
Permalink
Post by Chris F.A. Johnson
Post by Herb Martin
The following is a VERY naive way to accomplish "if any
files in a pattern exist" do some stuff with them.
Please suggest the best place to ask such questions, good
web sources for learning Linux/bash/etc scripting, and
Try the comp.unix.shell newsgroup.
Post by Herb Martin
#!/usr/bin/sh
for A in /etc/mail/move/*; do
if [ -f ${A} ] ; then
echo Do something with $A
echo And: mv /etc/mail/move/* /etc/mail/oldspam/
fi
done
###############end##################
That is a good way to do it, but it could be a little faster like
Can you elaborate on this? They look the same to me, same glob
expansion and same test.
Post by Chris F.A. Johnson
set -- /etc/mail/move/*
[ -f "$1" ] &&
for A
do
echo Do something with $A
echo And: mv /etc/mail/move/* /etc/mail/oldspam/
done
--
William Park <***@yahoo.ca>, Toronto, Canada
ThinFlash: Linux thin-client on USB key (flash) drive
http://home.eol.ca/~parkw/thinflash.html
BashDiff: Super Bash shell
http://freshmeat.net/projects/bashdiff/
Chris F.A. Johnson
2005-07-18 20:16:36 UTC
Permalink
Post by William Park
Post by Chris F.A. Johnson
Post by Herb Martin
The following is a VERY naive way to accomplish "if any
files in a pattern exist" do some stuff with them.
Please suggest the best place to ask such questions, good
web sources for learning Linux/bash/etc scripting, and
Try the comp.unix.shell newsgroup.
Post by Herb Martin
#!/usr/bin/sh
for A in /etc/mail/move/*; do
if [ -f ${A} ] ; then
echo Do something with $A
echo And: mv /etc/mail/move/* /etc/mail/oldspam/
fi
done
###############end##################
That is a good way to do it, but it could be a little faster like
Can you elaborate on this? They look the same to me, same glob
expansion and same test.
In the above script test is called for every file. In mine, below,
it is only called once.
Post by William Park
Post by Chris F.A. Johnson
set -- /etc/mail/move/*
[ -f "$1" ] &&
for A
do
echo Do something with $A
echo And: mv /etc/mail/move/* /etc/mail/oldspam/
done
--
Chris F.A. Johnson <http://cfaj.freeshell.org>
==================================================================
Shell Scripting Recipes: A Problem-Solution Approach, 2005, Apress
<http://www.torfree.net/~chris/books/cfaj/ssr.html>
G***@dodo.com.au
2005-07-18 23:52:45 UTC
Permalink
...
Post by Chris F.A. Johnson
Post by William Park
Can you elaborate on this? They look the same to me, same glob
expansion and same test.
In the above script test is called for every file. In mine, below,
it is only called once.
Post by William Park
Post by Chris F.A. Johnson
set -- /etc/mail/move/*
[ -f "$1" ] &&
^^^^^^^^^^^^^^--> isn't this a redundant test? Obfuscation? ;)
Post by Chris F.A. Johnson
Post by William Park
Post by Chris F.A. Johnson
for A
do
echo Do something with $A
echo And: mv /etc/mail/move/* /etc/mail/oldspam/
done
Grant.
Tony Lawrence
2005-07-22 00:54:10 UTC
Permalink
Post by G***@dodo.com.au
...
Post by Chris F.A. Johnson
Post by William Park
Can you elaborate on this? They look the same to me, same glob
expansion and same test.
In the above script test is called for every file. In mine, below,
it is only called once.
Post by William Park
Post by Chris F.A. Johnson
set -- /etc/mail/move/*
[ -f "$1" ] &&
^^^^^^^^^^^^^^--> isn't this a redundant test? Obfuscation? ;)
No, because the set might get nothing at all - empty dir or maybe even
no such directory at all.
--
Tony Lawrence
Unix/Linux/Mac OS X resources: http://aplawrence.com
Bit Twister
2005-07-06 04:54:40 UTC
Permalink
Post by Herb Martin
The following is a VERY naive way to accomplish "if any
files in a pattern exist" do some stuff with them.
find is another method to find files.
Post by Herb Martin
Please suggest the best place to ask such questions, good
web sources for learning Linux/bash/etc scripting, and
http://www.tldp.org/LDP/abs/html/index.html

For debugging or see what is going on in a script, you can put

set -xv # enable debugging
.
. # code to look at
.
set - # disable debugging


TIP:

Please bookmark the following, very large,
Frequently Asked Questions (faq) Search engine:

http://groups.google.com/advanced_group_search
key word(s) in the first box
*linux* in Newsgroup box. You need to use the two
asterisks around linux, pick English

If you want/need more control over the first box search,
http://www.google.com/help/refinesearch.html
Loading...