1

This works fine:

#!/bin/sh

ALTER="$1"
NAME="$2"

for pr in $(pgrep $NAME); do
    elapse=$(ps -o etime= -p $pr)
    [ "${elapse%:*}" -gt "$ALTER" ] && echo $pr
done

But if I try to switch it to CShell:

#!/bin/csh

set ALTER = "$1"
set NAME = "$2"

for pr in $(pgrep $NAME); do
    set elapse = $(ps -o etime= -p $pr)
    [ "${elapse%:*}" -gt "$ALTER" ] && echo $pr
done

I get an Illegal variable error. Any ideas?

terdon
  • 242,166
JuM
  • 47
  • 1
  • 10
  • 4
    Why do you like to convert something to csh at all? csh is not really useful for scripting. – schily Oct 07 '15 at 12:34
  • somebody told me to do it :/ – JuM Oct 07 '15 at 12:36
  • 3
    @JuM then they really, really hate you. Trying to script in csh is just painful and should be avoided at all costs really. – terdon Oct 07 '15 at 12:46
  • Okay thanks a lot for all the replies! :) – JuM Oct 07 '15 at 12:48
  • IMO csh should be avoided even as a CLI shell because you've got all the usual csh problems for your one-liners, AND you have to use a different language (e.g. sh or bash or ksh etc) for your scripts. As a CLI shell, there's nothing csh can do that bash, zsh, or a modern ksh can't do. – cas Oct 07 '15 at 21:48

2 Answers2

6

The first thing you should know about scripting in csh is that it is usually a very bad idea. That said, if you insist, the problems with your script are:

  • csh doesn't support the $() construct for command substitution, use ` ` instead.
  • csh doesn't support the for i ... do ... done syntax, use foreach i ... end instead.
  • csh doesn't do funky string manipulation like "${elapse%:*}". You'll have to get around it using some other tool.
  • I don't know how to get [ to work with csh (but it's probably possible), as a workaround, use if instead.

So, a working version of your script in csh would be:

#!/bin/csh
set ALTER = "$1" 
set NAME = "$2" 
foreach pr  (`pgrep "$NAME"`)
    set elapse = `ps -o etime= -p "$pr" | cut -d: -f1` 
    if ( "$elapse" > "$ALTER" ) echo "$pr"
end

Seriously though, don't script in csh, it will only cause you pain. Especially since all you really need is:

 ps -o pid=,etime= -p $(pgrep $NAME) | cut -d: -f1 | 
        awk -vval="$ALTER" '$2>val{print $1}'
terdon
  • 242,166
  • Version: $Id: csh-faq,v 1.7 95/09/28 12:52:17 tchrist Exp Locker: tchrist $ Happy Birthday! Twenty years later and people are still being told to use csh. – bishop Oct 07 '15 at 14:14
  • 1
    [ is an external command; I'd be very surprised if it doesn't work. – Random832 Oct 07 '15 at 15:08
  • @Random832 it's both a builtin and an external one, but yes, good point. /usr/bin/[ 10 > 5 ] && echo y seems to work in csh. [ 10 > 5 ] && echo y doesn't. I don't know the details, I'm happy to remain ignorant of csh :) – terdon Oct 07 '15 at 15:10
  • Well, > isn't actually a supported operator in the [ command; you need -gt and you need to be comparing integers. By the way, check for a file named 5 in the directory you tested it in. – Random832 Oct 07 '15 at 15:13
  • @Random832 d'oh! Yup, that created 5. However, this still fails in csh: [ 5 -gt 4 ] && echo y. Anyway, answer edited to reflect that csh could probably use [ if not for my ignorance. Thanks. – terdon Oct 07 '15 at 15:16
  • Do you also got an idea how I can avoid pgrep? I tried something like that: foreach pr (grep "$NAME" | awk '{$2}') but it doesn't work fine... – JuM Oct 08 '15 at 07:01
  • @JuM well no, that wouldn't work. grep has nothing to do with pgrep, it needs an input. Why would you want to avoid pgrep? – terdon Oct 08 '15 at 10:52
3

${var%$pattern} is a POSIX-shell construct (introduced by ksh) not available in csh.

You could use expr here:

expr "$elapse" : '\([0-9]*\)' '>' "$ALTER" > /dev/null && echo $pr

But I would first

  1. avoid csh
  2. avoid csh
  3. avoid loops in shell scripting. Here the whole thing can be done by piping ps to awk in a syntax compatible with most shells.