Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

The tool batch that comes with the atd daemon is pretty useful in principle, running commands only when the system utilisation falls below a certain level (by default, 1.5). However, using it (and also at) is pretty ugly by modern standards: you either have to feed a script which can be run by /bin/sh, or type commands interactively into a basic prompt with no completion, color-coding, etc.

What would be really nice is a command prefix tool, more like nice, that one can put in front of any command to add it to the batch queue (and a similar utility for at would be handy, although that's not the main point of my question). For example, it might work like this:

my-batchifying-command python some_longrunning_computational_script.py

Does such a thing exist? If not, how might it be created? I use zsh for my main shell, but a bash answer would be equally OK and might have wider applicability.

share|improve this question

With zsh for simple commands:

my-batch() {print -r -- ${(qq)@} | batch}

my-batch python some_longrunning_computational_script.sh

would do it.

If you need more complex things like loops or redirections, you could do:

my-batch eval 'for i in ...; done'

my-batch eval 'echo test > /some/file'

But remember to use sh, not zsh syntax.

If you want to be able to avoid the eval, you could use this trick:

alias my-batch=':||'
  if [[ $1 = my-batch\ * ]]; then
    print -r -- "${1#my-batch }" | batch

Again, be sure to use sh syntax.

Beware that it can be only one command (actually one pipeline). If you need more than one, use braces:

my-batch { ls > /tmp/a; date > /tmp/b; }

The idea above is that the my-batch command does nothing, does not even evaluate the arguments of the command because for instance my-batch echo $(date) expands to :|| echo $(date), and it's preexec which is run each time a command line is accepted that does the job instead.

For preexec, $1 is the full command line untouched. We just check if it starts with "my-batch ", strip that and send the rest to batch.

That explains why my-batch has to be at the beginning of the line. cmd && my-batch ... won't work for instance, and you can't do things like my-batch foo || bar, because it's actually going to be interpreted as :|| foo || bar.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.