1

I'm keeping an eye on a process in FreeBSD using a script which outputs the current status of the job.

Using the csh builtin command repeat, I'd like to run the script every 2 seconds, so naively I'd like to do something like this:

  • repeat 100000 ./dumpstatus ; sleep 2

Obviously the semicolon won't work as intended, but I can't find the correct syntax to include it.

I can workaround by invoking a new shell instance under repeat:

  • repeat 100000 sh -c 'path/to/script/dumpstatus ; sleep 2'

but that's hardly ideal, and doesn't take a path from the current pwd either which is annoying :)

I've also tried repeat 10000 ( ./dumpstatus ; sleep 2) with and without escaping the brackets, that doesn't work either and I'm not completely sure why.

What is the correct way to do this, without invoking sh -c, so the semicolon gets interpreted as I would wish?

agc
  • 7,223
Stilez
  • 1,261

2 Answers2

2

I believe it's not possible without invoking a shell, as the csh manpage states (in part):

repeat count command

The specified command, which is subject to the same restrictions as the command in the one line if statement above, is executed count times. ...

combined with the if description:

if ( expr ) command

... command must be a simple command, not an alias, a pipeline, a command list or a parenthesized command list, but it may have arguments.

... seems to me to rule out other options.

I am unable to reproduce your $PWD failure in the sh -c example. Given this script in my home directory:

$ cat ~/script.sh
#!/bin/sh
echo $0 pwd is $PWD

And a sample run of:

$ csh
$ echo $version
tcsh 6.18.01 (Astron) 2012-02-14 (x86_64-unknown-linux) options wide,nls,dl,al,kan,rh,color,filec

$ cd /tmp $ repeat 2 sh -c '~/script.sh; sleep 2' /home/me/script.sh pwd is /tmp /home/me/script.sh pwd is /tmp

... shows script.sh executing from the parent shell's $PWD.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
0

Since repeat can't parse a command list, it can't be done. I wish that csh man could say it plainly like this:

 repeat count command
         The specified command must be a simple command, (not a pipeline, not a
         command list, nor a parenthesized command list), and is executed count
         times.  I/O redirections occur exactly once, even if count is 0.

Note the single redirection limit, which makes using a while loop workaround impractical. Example, which doesn't print 9 lives:

echo lives | repeat 9 cat | wc -l
1

Source: the actual quote of man csh, (but read the entry on repeat first, then the if entry), is a bit roundabout:

COLUMNS=90 man csh | egrep -A 7 ' (repeat|if).*and$' | sed -n '1,13{s/^ \{10\}//p}'
 if (expr) command
         If the specified expression evaluates to true, then the single
         command with arguments is executed.  Variable substitution on
         command happens early, at the same time it does for the rest of the
         if command.  command must be a simple command, not a pipeline, a
         command list, or a parenthesized command list.  Input/output redi‐
         rection occurs even if expr is false, i.e., when command is not exe‐
         cuted (this is a bug).
 repeat count command
         The specified command, which is subject to the same restrictions as
         the command in the one line if statement above, is executed count
         times.  I/O redirections occur exactly once, even if count is 0.
agc
  • 7,223