I note in the crontab(5) man page, this:
The ``sixth'' field (the rest of the line) specifies the command to be
run. The entire command portion of the line will be executed by
/bin/sh or by the shell specified in the SHELL variable of the
cronfile.
So, you may want to specify bash either with
SHELL=/bin/bash
or, as the above affects all cron scripts, this
* * * * 1-5 root bash /home/xxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/jmeter-cron-randomise.sh >> /home/xxxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/cron.log
# ...............^^^^
There are various possible failure points in your script. First of all, rm *.old*
will use globbing to create a list of all matching files, and that can deal with file names containing whitespace. Your script, however, assigns a variable to each result of the glob and does that without quoting. That will break if your file names contain whitespace. For example:
$ ls
'file name with spaces.old.txt' file.old.txt
$ rm *.old.* ## works: both files are deleted
$ touch "file.old.txt" "file name with spaces.old.txt"
$ for i in ./*; do oldfile=$i; rm -v $oldfile; done
rm: cannot remove './file': No such file or directory
rm: cannot remove 'name': No such file or directory
rm: cannot remove 'with': No such file or directory
rm: cannot remove 'spaces.old.txt': No such file or directory
removed './file.old.txt'
As you can see, the loop failed for the file with spaces in its name. To do it correctly, you would need to quote the variable:
$ for i in ./*; do oldfile="$i"; rm -v "$oldfile"; done
removed './file name with spaces.old.txt'
removed './file.old.txt'
The same issue applies to pretty much every use of $i
in your script. You should always quote your variables.
The next possible issue is that you seem to expect that *.old.*
matches files with the extension .old
. It doesn't. It matches "0 or more characters" (*
), then a .
, then "old", then another .
and then "0 or more characters again". This means that it will not match something like file.old
, but only something like `file.old.foo:
$ ls
file.old file.old.foo
$ for i in *; do if [[ "$i" == *.old.* ]]; then echo $i; fi; done
file.old.foo
So, no match foe file.old
. In any case, your script is far more complex than needed. Try this one instead:
#!/bin/bash
for i in *; do
if [[ -f "$i" ]]; then
if [[ "$i" == *.old ]]; then
rm -v "$i" || echo "rm failed for $i"
else
echo "$i doesn't have an .old extension"
fi
cp -v "$i" "$i".old
else
echo "$i is not a file"
fi
done
Note that I added -v
to the rm
and cpwhich does the same thing as what you were doing with your
echo` statements.
This isn't perfect since when you find, for example, file.old
, that will be removed and, later on, the script will try to copy it and fail since the file no longer exists. However, you haven't explained what you script is actually attempting to do so I can't fix that for you unless you tell us what you are really trying to accomplish.
If what you want is to i) remove all files with the .old
extension and ii) add the .old
extension to any existing files that don't have it, all you really need is:
#!/bin/bash
for i in *.old; do
if [[ -f "$i" ]]; then
rm -v "$i" || echo "rm failed for $i"
else
echo "$i is not a file"
fi
done
## All the ,old files have been removed at this point
## copy the rest
for i in *; do
if [[ -f "$i" ]]; then
## the -v makes cp report copied files
cp -v "$i" "$i".old
fi
done
Best Answer
To form an answer from the comments:
Many people out of habit run their scripts with
sh
instead ofbash
. This is a good practice if portability is a concern, but many people do so because they're copying something they've seen without understanding it.Unless your script needs to run on a non-desktop Linux system (e.g., running shell scripts on Android devices is quite different), I recommend using the Bash shebang line at the beginning:
This line, when it's the first line in the script, determines which interpreter (shell such as bash or sh, Python, etc.) is called to execute it. If you use the above line, you'll get the same behavior (almost) as you do from the command line, assuming you use the default shell. If for reasons of portability or preference you use a different shebang line, be aware that you'll have to consult the documentation for the shell you've referenced, even if the shell you reference is a symlink to Bash.