This may not be the answer you are looking for, but a simple Makefile would seem to satisfy your requirements. Make terminates execution on error out of the box, and its purpose is to avoid repeating processing steps. Especially if (at least most of) your commands generate an output file, it would be a rather natural fit. If not, keeping a simple state file is a common Make idiom to mark a command sequence as succesfully completed.
(If you are new to Make, note well that each command in a target needs to have a literal tab for indentation.)
.PHONY: all
all: .command1-done .command2-done
.command1-done:
command1
touch $@
# Comment out the dependency to avoid forcing sequential execution
.command2-done: .command1-done
command2
touch $@
.PHONY: clean
clean:
rm -f .*-done
So, this runs command1 and, if it succeeds, proceeds to the next command in the recipe, which runs touch on the semaphore file (the Make variable $@ expands to the current target name). If this succeeds, too, it runs command2, and similarly creates its "done" file if it succeeds. Running make again will tell you that no commands need to be run:
$ make
command1
touch .command1-done
command2
touch .command2-done
$ make
make: Nothing to be done for `all'.
If you actually care about the execution order of targets, that is usually because there is a dependency (command2 fails or, worse, produces incorrect results unless it is run after command1). Such dependencies need to be declared -- I put in an example of how to declare such a relationship. If there is no dependency, you should probably not declare one; then, Make will run your targets in arbitrary order (though the versions I have worked with are generally predictable); or you can have Make run them in parallel with make -j.
(The state file usually starts with a dot, to keep it hidden from a regular directory listing.)
More realistically, perhaps your commands actually generate some output:
.PHONY: all
all: grep.out wc.out
grep.out:
grep -Fw Debian /etc/motd >$@
wc.out: grep.out
wc -l <$< >$@
(Unfortunately, shell redirection will create the output file even if the target fails. A workaround is to use a temporary output file, then move it into place only on success:
.PHONY: all
all: grep.out wc.out
grep.out:
grep -Fw Debian /etc/motd >[email protected]
mv [email protected] $@
wc.out: grep.out
wc -l <$< >[email protected]
mv [email protected] $@
.PHONY: clean
clean:
rm -f .*.tmp
But anyway, this is already getting too long.)
sedor similar). But this sounds like the wrong sort of solution to me. What's the real problem here? (Something likemakemight actually be useful for this potentially also.)