3

I try to retrieve the result from $_ inside a tcsh script itself sourced by another tcsh script (I'll refer to them respectively as the inner and outer script). But $_ is not set with the value I expect (being the last command executed).

outer code:

#!/usr/bin/tcsh

set lastCmd0 = ($_)
echo "${lastCmd0}"
echo "$0"
source inner
echo "enOuter"

inner code:

#!/usr/bin/tcsh

set lastCmd1 = ($_)
echo "${lastCmd1}"
echo "$0"
echo "endInner"

Here are the output when calling source outer:

source outer 
tcsh
source outer 
tcsh
endInner
enOuter

Q 1 Why is there two source outer, the second one shoudn't be source inner?

Here are the output when calling ./outer:

./outer

./outer
endInner
enOuter

Q 2 Why $_ isn't set when sourcing inner ?

It seems that $_ is never set again when executing a script, I don't know if it is a normal or not. Anyway if it is not possible to use $_, is there an alternative secure way to get the last command executed inside a script ?

  • Why would you even need $_ from inside a script? This seems like a XY problem to me. I think you're better off describing what exactly you're trying to do, rather than use an "abstract" example like this. – Martin Tournoij Jan 29 '16 at 0:37
  • As to the answer "why does tcsh behave like this?" That's because it's crappy code dating back to the 1970s when Bill Joy write the first csh as a student and later admitted that he "didn't really know what he was doing". There are many quirks in (t)csh scripting, and is typically best avoided altogether if possible. – Martin Tournoij Jan 29 '16 at 0:39
  • I agree with you, but some other scripts in the project are in tcsh (the project is old) and -- for now -- it's easier to not rewrite them all. But I definitely will have to rewrite them one day. – ahonorat Jan 29 '16 at 9:49
1

tcsh can update the items in argv() if you provide parameters to the source command, but does not alter $0 or $_.

You can see what is going on by changing the messages to show which variable is printed, and which script does it. First "outer":

#!/usr/bin/tcsh

set lastCmd0 = ($_)
echo 'O:$lastCmd0'"=${lastCmd0}"
echo 'O:$0'"=$0"
source inner
echo 'O:endOuter'

and then "inner"

#!/usr/bin/tcsh

set lastCmd1 = ($_)
echo 'I:$lastCmd1='"${lastCmd1}"
echo 'I:$0'"=$0"
echo 'I:endInner'

Output:

> tcsh -f
> source ./outer
O:$lastCmd0=source ./outer 
O:$0=tcsh
I:$lastCmd1=source ./outer 
I:$0=tcsh
I:endInner
O:endOuter

and

> source ./outer first second
#argv: 2
O:$lastCmd0=source ./outer first second 
O:$0=tcsh
I:$lastCmd1=source ./outer first second 
I:$0=tcsh
I:endInner
O:endOuter

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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