To start with, please use ***
[code][/code]*** tags around your code and data, to preserve the original formatting and to improve readability. Do
not use quote tags, bolding, colors, "start/end" lines, or other creative techniques.
Let me go line-by-line, so I can point out some things.
Code:
# touch < date "+%Y-%m-%d-%H-%M-%S"
Yes, it's a comment, but the code in it is wrong. You can't directly run multiple commands together like that. You have to use a
command substitution. As it is, "
date" would be treated as a filename for redirection instead. But then,
touch doesn't accept strings from stdin by default either.
Code:
LOGFILE="log-$NOW.log"
touch $LOGFILE
QUOTE ALL OF YOUR VARIABLE EXPANSIONS. You should never leave the quotes off a parameter expansion unless you explicitly want the resulting string to be word-split by the shell (globbing patterns are also expanded). This is a vitally important concept in scripting, so train yourself to do it correctly now. You can learn about the exceptions later.
http://mywiki.wooledge.org/Arguments
http://mywiki.wooledge.org/WordSplitting
http://mywiki.wooledge.org/Quotes
Now, in this specific case it doesn't cause problems because the expanded string doesn't have any whitespace or globbing characters. But it's a good idea to always do it properly anyway.
And since environment variables are generally all upper-case, it's recommended practice to keep your own user variables in lower-case or mixed-case to help differentiate them.
Code:
FILES=/Users/zaphod/Desktop/me/data/*.dat
for f in $FILES
do
This is ok, as the unquoted $FILES variable will glob expand properly. But as I just said, it's better to keep variables quoted whenever possible. A better technique would be to use an
array (assuming
bash or another shell that supports them).
Code:
files=( /Users/zaphod/Desktop/me/data/*.dat )
for f in "${files[@]}"; do
Or just use the globbing pattern directly after
for.
You might also consider not hard-coding the file path like that, but instead
cd'ing into that directory at the beginning of the script, so you could use a simple "
for f in *.dat".
Note too that many scripters feel that it's better to place the "
do/then" keywords on the same line as the "
for/while/until/if" keywords, as they are not separate commands but the closing indicators for the test block, paired directly with the opening keyword. Putting them together on one line thus more clearly separates the outside block from the inside block.
Again, not really a problem, but this seems to me like a bit of pointless complexity, and a slightly non-transparent one. I'd personally just use "
echo; echo", or "
printf '\n\n'" if I wanted to print two blank lines (
learn about printf here).
Code:
cat -u | (tail -n 1 -q $f) > "\n" >> $LOGFILE
I can't understand what this is supposed to be doing. The initial
cat command (-u is unrecognized in the gnu version) would just sit there waiting for input from stdin. If it ever got some, then it would try to pipe it into
tail (which is also running in a pointless subshell), but tail is already reading from a file, and will probably ignore stdin. Finally, it tries to output it's results to both "
\n" and to "$LOGFILE"? That doesn't work either.
redirections) are processed left-to-right at the beginning of command parsing, so the second one simply overrides the first one. In any case it certainly doesn't add a newline to the output, as you seem to think it does.
chrism01 has already posted how to run
tail correctly. But if you ever need to add a newline to a file, just run "
echo >> filename" after the main command.
Finally, beware the
Useless Use Of Cat!