On 11:36 01 Mar 2002, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote:
| I have a machine running 7.2, samba file server for windows clients. The
| software we use leave quite a bit of junk files for temp saves, crashes and
| the like. I am attempting to have cron run a script to file from shared
| directory with said extension. The problem are the (windows spaces), I
| would like to avoid the extra overhead in renaming files I will delete
| moments latter so...
|
| this is where I am the attempting to pipe to sed to escape the "\ " the
| space. Also tried to quote the full path. Both work from the command line?
| What gives? Suggestions?
Your problem is that your fundamental approach is wrong. You almost
NEVER want to "escape" special characters in variable values. Instead,
arrange that they don't get USED as specials, by doing correct quoting.
| #! /bin/bash
| # Purge Junk Files from Samba Drive
| for ext in *.ac$ *.bak *.bk? back*.cdr *.chk *.dmp *.err *.sv$ *.tmp ~*.*
Ok, here's your first bug: ALL these patterns should be quoted. File
expansion takes place on all commands, so if this script just happens
to run in a directory with a file matching one of the patterns, that
pattern will be replaced with the filename, and so in the loop, $ext
will be a plain filename, not a pattern. You're only getting patterns
in $ext inside the loop because the patterns _aren't_ matching in the
directory where the script is running. Instead, you should be saying this:
for ext in '*.ac$' '*.bak' '*.bk?' 'back*.cdr' '*.chk' '*.dmp' '*.err' '*.sv$'
'*.tmp' '~*.*'
| do
| find /home2/Temp/Test -type f -iname "$ext" |
This is ok.
| sed -e 's/[ ] [ ]*/ /g
| s/[ ]/\\ /g' |
This is totally unnecessary.
| while read name
Use "read -r name" here - it does a "raw" read. Normally the read command
does slosh (\) interpretation and line continuation, which is a major
PITA in scripts.
| do
| echo $name #I can see the output
|to rm
This, also, should be quoted because you want to see here the "pure" value
in $name, without any fiddling by the shell. Outside quotes, $name will be
subject to space separation (meaning that "foo bar" will be turned into
two words "foo" and "bar" for the echo command, and printed as "foo bar"
- note the single space inserted between the two strings by echo, and the
consequent loss of the multiple spaces, which you may care about.) Also,
the value will be subject to globbing and thus unfortunately named files
(like a literal "fred*.bak") may be misreported because the shell may
expand that to match several filenames and hand them to echo to print).
So say:
echo "$name"
instead.
| rm -f $(echo $name)
This is even worse. Here you're handing an unquoted string to echo as
above, and _then_ handing the unquoted output of the echo command to
rm. Instead, say:
rm -f "$name"
which is shorter, faster, and has no quoting problems.
After fixing the quoting, you script may look a bit like this:
for ext in '*.ac$' '*.bak' '*.bk?' 'back*.cdr' '*.chk' '*.dmp' '*.err' '*.sv$'
'*.tmp' '~*.*'
do
find /home2/Temp/Test -type f -iname "$ext" |
while read -r name
do
echo "$name" #I can see the output to rm
rm -f "$name"
done
done
Just a stylistic point: I like to use slosh extension and put the pipe
on the next line when writing multiple pipes, so I'd take this:
find /home2/Temp/Test -type f -iname "$ext" |
while read -r name
and rewrite it as:
find /home2/Temp/Test -type f -iname "$ext" \
| while read -r name
because in this way it is more obvious to the reader that the "while"
is reading from a pipe. Functionally it is exactly the same, but there
is less chance for another person to miss seeing the "|" on the end of
the line.
However, this can all be reduced even further:
find /home2/Temp/Test -type f \
\( -iname '*.ac$' \
-o -iname '*.bak' \
-o -iname '*.bk?' \
-o -iname 'back*.cdr' \
-o -iname '*.chk' \
-o -iname '*.dmp' \
-o -iname '*.err' \
-o -iname '*.sv$' \
-o -iname '*.tmp' \
-o -iname '~*.*' \
\) -print -exec rm -f {} ';'
Here we're putting all the tests in the "find" command. There's no
passing of strings from one command to another at all, except for the
"find" command passing each matching filename to the "rm" command in
place of the "{}" word in the -exec list. The -print there serves the
same purpose as your "echo $name" line - debugging or reporting.
Also note the two quoting styles used:
\( \) The ( and ) characters are special to the shell, so we're
quoting them here. The \ quotes the next character.
';' Semicolons are also special, so it's quoted too.
Neither way is inherently better - I could as well have written '('
and \; to achieve the same end - it's just finger habits.
I would recommend that you also add a test for the age of the file; people
get really annoying when you remove a file they're using right now.
Adding a "-mtime +7" for example would only remove files more than
7 days old, which will keep your junk files count down while leaving
active files alone.
Doubtless someone will also mention xargs. In this case the probably
number is files is so low that there's negligible performance benefit
involved, and the command argument limit isn't involved at all (the
other command use for xargs).
<FLAME>More important, though, is that xargs suffers from much the same
design flaw that your original script did - it has quoting bugs, and
readily mangles unusual filenames a lot like your script was doing. This
so annoyed me that I NEVER use xargs, and wrote a less "feature rich"
but also nonmangling version here:
http://www.zip.com.au/~cs/scripts/xxargs
precisely because xargs is a broken piece of junk.</FLAME>
Anyway, I hope this has made more clear the source of your troubles with
this script, and a path to avoiding them.
Cheers,
--
Cameron Simpson, DoD#743 [EMAIL PROTECTED] http://www.zip.com.au/~cs/
The Web site you seek
cannot be located but
endless others exist
- Haiku Error Messages http://www.salonmagazine.com/21st/chal/1998/02/10chal2.html
_______________________________________________
Seawolf-list mailing list
[EMAIL PROTECTED]
https://listman.redhat.com/mailman/listinfo/seawolf-list