d commandUsage: d [ -f file ] c[n][a][p] cmd arg ... or: d [ -f file ] m[n][a][p] [ make_arg ... ] or: d [ -f file ] s[n][a][p] [ additional_arg ... ] or: d [ -f file ] h
Do a task in the background, with its stdout and stderr redirected to a file called out
or to file
or to a file named by a $yostD_OUTFILE environment variable.
The d command usually does
mv ,out out
and then creates a new out file,
but d can be told to append to out instead.
The task argument is composed of individual letters:
One of these is required: cDo the following command - redirection and piping work if quoted. mDo a make. sDo the same command again (extract the last command from out, and run it again (without 'nice' unless you ask for it again).hPrint a history of what happened in this outfile.These are optional: nDo it nicely.aAppend to out.pJust print the command that would be executed; don't run it.
The d command comes along with several helper shell functions:
qtail -f outcat outqttail -20 outcqclear ; qcqqclear ; qqwqwait "$@" ; printf "\b" ; qqwqtwait "$@" ; printf "\b" ; qt
The output from d into the file out consists of
prologue
output from the command
epilogue
as shown in the example below, which does this:
c) in the background, with output to the out file.
s) comand again, with nice (n), appending (a) the output to the existing out file.
out file.
p) if we try to run the same command again, using ‘d s’.
h) of commands and results contained in the out file.
223 Z% d c 'sleep 5 ; echo Hello folks' [3] 3937 224 Z% [3] + 3937 done yostD_runCmd 224 Z% d sna [ sleep 5 ; echo Hello folks ] [3] 3965 225 Z% [3] + 3965 done yostD_runCmd 225 Z% qq =dbegin 2006-07-08T16:28:11 PDT Sat =dhost Yost.com =dwd /Users/yost =dcmd sleep 5 ; echo Hello folks Hello folks 5.06 real 0.00 user 0.02 sys =dstat 0 =dend 2006-07-08T16:28:17 PDT Sat ======= ======================================================================= =dbegin 2006-07-08T16:28:19 PDT Sat =dhost Yost.com =dwd /Users/yost =dcmd nice sleep 5 ; echo Hello folks Hello folks 5.06 real 0.00 user 0.02 sys =dstat 0 =dend 2006-07-08T16:28:24 PDT Sat ======= ======================================================================= 226 Z% d sp sleep 5 ; echo Hello folks 227 Z% d h =dcmd sleep 5 ; echo Hello folks =dstat 0 =dcmd sleep 5 ; echo Hello folks =dstat 0 228 Z% |
To use the d command and its helpers, you need to source d.sh from your zsh, bash, ksh, or sh. If your system does not have the tac command, you will need to install it for the s command to work.
Here is d.sh:
# Source this file into sh, ksh, bash, or zsh
# See http://Yost.com/computers/d
#
# Needs the 'tac' command, which cats lines from end to beginning of file.
# Requires shell procedures.
#
# Bugs:
# * Quoting arguments doesn't work properly.
# * The background job is shown in a weird way, not showing the command(s)
# you're really running.
# * If you have a bad old shell, there won't be a job number handle on the
# backgrounded task
#
# The timing of commands could be better.
#
# I have tested this only with zsh 4.2.3
#
# Author: Dave@Yost.com
# 2.0 1991-04-xx
# 4.0 2004-12-19
# 5.0 2006-07-09
# 5.1 2006-07-10
# 5.2 2006-07-14
# 5.3 2006-12-14 fix "d s" bug when out file doesn't exist
# 5.4 2006-12-27 Make it work with bash, ksh, and sh
#-------------------------------------------------------------------------------
yostD_usage () {
echo 1>&2 "
Usage: d [ -f <file> ] c[n][a][p] <cmd> <arg> ...
or: d [ -f <file> ] m[n][a][p] [ <make-arg> ... ]
or: d [ -f <file> ] s[n][a][p] [ <additional-arg> ... ]
or: d [ -f <file> ] h
Do a task in the background, with its stdout and stderr redirected to
a file called 'out' or <file> or named by \$yostD_OUTFILE (environment variable).
The d command usually does
mv ,out out
before creating a new out file but can be told to append to out instead.
The first argument to the d command is called the task argument.
The following letters in the task argument determine the task that is run:
One of these is required:
c - Do the following command - redirection and piping work (if escaped).
m - Do a make.
s - Do the same command again (extract the last command from <file>,
and run it again (without 'nice' unless you ask for it again).
h - Print a history of what happened in this out file (h by itself).
These are optional:
p - just print the command that would be executed; don't run it
n - Do it 'nice'ly.
a - Append to $yostD_OUTFILE
See http://Yost.com/computers/d
"
return 2
}
#-------------------------------------------------------------------------------
d() {
yostD_setOutFileVariableIfNotSet
yostD_args "$@" \
&& \
if [[ "$yostD_optPrint" = true ]] ; then
yostD_print
else
yostD_run
fi
}
#-------------------------------------------------------------------------------
yostD_setOutFileVariableIfNotSet() {
if [[ -z "${yostD_OUTFILE:-}" ]] ; then yostD_OUTFILE=out ; fi
}
#-------------------------------------------------------------------------------
yostD_args() {
yostD_optAppend=false
yostD_optNice=
yostD_optNicePrefix=
yostD_optPrint=false
yostD_optPrintAll=false
yostD_optSame=false
if [[ $# = 0 ]] ; then return $(yostD_usage) ; fi
if [[ "${1:-}" = -f ]] ; then
yostD_OUTFILE=$2
shift
shift
fi
yostD_task=$1
shift
# There must be exactly one command.
case "$yostD_task" in
""|*[\`~!@#$%^\&*\(\)_-+={[}\]|\\:\;'"'"'"\<,\>.?/bdefgijkloqrtuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]*)
return $(yostD_usage)
;;
h)
yostD_optPrint=true
yostD_optPrintAll=true
;;
*c*m* | *m*c* | *c*s* | *s*c* | *m*s* | *s*m* )
return $(yostD_usage)
;;
*c*)
if [[ $# = 0 ]] ; then
return $(yostD_usage)
else
yostD_cmd="$@"
fi
;;
*m*)
yostD_cmd=make
if [[ -n "$@" ]] ; then
yostD_cmd="$yostD_cmd $@"
fi
;;
*s*)
yostD_optSame=true
yostD_cmd="$(yostD_findSameCmd)"
if [[ $? != 0 ]] ; then
return 2
fi
if [[ -n "$@" ]] ; then
# Shell syntax. Hrmph.
#if [[ $1 = ${yostD_cmd[1]} ]] ; then
# echo 1>&2 "d: extra args to s are probably wrong"
# return 2
#fi
yostD_cmd="$yostD_cmd $@"
fi
;;
*)
return $(yostD_usage)
esac
# And there can be optional modifiers.
case "$yostD_task" in
*a*)
yostD_optAppend=true
esac
case "$yostD_task" in
*n*)
yostD_optNice="nice"
yostD_optNicePrefix="nice "
esac
case "$yostD_task" in
*p*)
yostD_optPrint=true
esac
return $(yostD_ensureShellSet)
}
#-------------------------------------------------------------------------------
yostD_findSameCmd() {
if [[ ! -r $yostD_OUTFILE ]] ; then
echo 1>&2 "d: can't run same command again; can't read file '$yostD_OUTFILE'"
return 2
fi
yostD_cmd=$(
tac $yostD_OUTFILE 2> /dev/null \
| sed -n '
/^=dcmd *nice */{
s///p
q
}
/^=dcmd */{
s///p
q
}
'
)
if [[ -z "$yostD_cmd" ]] ; then
echo 1>&2 "d: can't run same command again; can't find usable command in file '$yostD_OUTFILE'"
return 2
fi
echo "$yostD_cmd"
}
#-------------------------------------------------------------------------------
yostD_ensureShellSet() {
if [[ -n "$SHELL:-" ]] ; then
SHELL=$(which zsh) \
|| SHELL=$(which bash) \
|| SHELL=$(which ksh) \
|| SHELL=$(which sh) \
|| (
echo 1>&2 "d: Can't operate because you have no SHELL environment variable"
return 2
)
fi
}
#-------------------------------------------------------------------------------
yostD_print() {
if [[ "$yostD_optPrintAll" = true ]] ; then
sed -n '
/^=dcmd/p
/^=dstat/p
' $yostD_OUTFILE
else
echo ${yostD_optNicePrefix}$yostD_cmd
fi
return 0
}
#-------------------------------------------------------------------------------
yostD_run() {
if [[ "$yostD_optSame" = true ]] ; then
echo 1>&2 "[ $(yostD_print) ]"
fi
if [[ "$yostD_optAppend" != true ]] ; then
yostD_mvOutFile
fi \
&& \
yostD_runCmd &
}
#-------------------------------------------------------------------------------
yostD_mvOutFile() {
mv -f $yostD_OUTFILE $(yostD_mkBackupName "${yostD_OUTFILE:-out}") 2> /dev/null
echo -n '' >> $yostD_OUTFILE
}
#-------------------------------------------------------------------------------
yostD_runInternal() {
if [[ -n "$yostD_optNice" ]] ; then
time $yostD_optNice $SHELL -c "$yostD_cmd"
else
time $SHELL -c "$yostD_cmd"
fi
}
yostD_runCmd() {
{
# We use sh -c so pipes and semcolons work.
yostD_outputPrologue \
&& \
runInternal
yostD_outputEpilogue
yostD_beep
} \
>> $yostD_OUTFILE 2>&1
}
#-------------------------------------------------------------------------------
yostD_outputPrologue() {
echo '=dbegin '$(yostD_formattedDate)"
=dhost ${HOST:-$(hostname)}
=dwd $(pwd)
=dcmd ${yostD_optNicePrefix}$yostD_cmd"
}
#-------------------------------------------------------------------------------
yostD_outputEpilogue() {
echo "=dstat $?
=dend "`yostD_formattedDate`"
======= ======================================================================="
}
#-------------------------------------------------------------------------------
yostD_beep() {
printf "\b" > /dev/tty
}
#-------------------------------------------------------------------------------
yostD_formattedDate() {
date '+%Y-%m-%dT%H:%M:%S %Z %a'
}
#-------------------------------------------------------------------------------
yostD_mkBackupName() {
echo ,"$1"
}
#===============================================================================
# Also useful:
# j() { jobs "$@" ; }
# k() { kill %% ; }
if ! type q \
&& ! type qq \
&& ! type qt \
&& ! type cq \
&& ! type cqq \
&& ! type wq \
&& ! type wqt \
&& ! type mvout ; then
yostD_qOK=true
else
yostD_qOK=
fi > /dev/null 2>&1
if [[ $yostD_qOK = true ]] ; then
q () { tail -f ${yostD_OUTFILE:-out} ; }
qq () { cat ${yostD_OUTFILE:-out} ; }
qt () { tail -20 ${yostD_OUTFILE:-out} ; }
cq () { clear ; q ; }
cqq () { clear ; qq ; }
wq () { wait "$@" ; printf "\b" ; qq ; }
wqt () { wait "$@" ; printf "\b" ; qt ; }
mvout() { mv -f ${yostD_OUTFILE:-out} $(yostD_mkBackupName "${yostD_OUTFILE:-out}") ; }
else
echo 1>&2 "d.sh can't create the 'd' helper commands because of conflicts"
fi
#-------------------------------------------------------------------------------
# Copyright 2006 Dave Yost <Dave@Yost.com>
# This version is
# d.sh 5.4 2006-12-27
# which at time of this publication can be found at:
# http://Yost.com/computers/d
# Redistribution and use in the form of source code or derivative data built
# from the source code, with or without modification, are permitted provided
# that the following conditions are met:
# 1. THE USER AGREES THAT THERE IS NO WARRANTY.
# 2. If and only if appropriate, the above phrase "This version is" must be
# followed by the phrase "a modified form of" or "extracted from" or
# "extracted and modified from".
# 3. Redistributions of source code must retain this notice intact.
# 4. Redistributions in the form of derivative data built from the source
# code must reproduce this notice intact in the documentation and/or other
# materials provided with the distribution, and each file in the derivative
# data must reproduce any Yost.com URI included in the original distribution.
# 5. Neither the name of Dave Yost nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
# This notice comprises all text from "Copyright" above through the end of
# this sentence.
|
I have tested this only with zsh 4.2.3.
Please feel free to send bug fixes.
out file doesn't exist