4

I'm trying to do a simple tcsh script to look for a folder, then navigate to it if it exists. The statement evaluates properly, but if it evaluates false, I get an error "then: then/endif not found". If it evaluates true, no problem. Where am I going wrong?

#!/bin/tcsh
set icmanagedir = ""
set workspace = `find -maxdepth 1 -name "*$user*" | sort -r | head -n1`
if ($icmanagedir != "" && $workspace != "") then
  setenv WORKSPACE_DIR `readlink -f $workspace`
  echo "Navigating to workspace" $WORKSPACE_DIR
  cd $WORKSPACE_DIR
endif

($icmanagedir is initialized elswehere, but I get the error regardless of which variable is empty)

Kayson
  • 425
  • 3
  • 15
  • It would be good to provide a [mcve], so people can reproduce the problem. That being that, I would guess that adding quotes around the `$icmanagedir` and `$workspace` will fix your problem: `if ("$icmanagedir" != "" && "$workspace" != "") then`. Also try adding a space after the `(` and before the `)`; some tcsh versions are finicky about that (and one reason you usually don't want to write programs in tcsh). – Martin Tournoij Sep 07 '17 at 20:39
  • Adding the quotes around the variables and the spaces around the parentheses didn't help. If I put the code (updated) by itself in a script, I still get the error. – Kayson Sep 07 '17 at 20:45
  • Hm, your example runs fine for me (the `if` is never entered as `icmanagedir` is always `""`). You're missing the closing backtick in the `setenv WORKSPACE_DIR ..` line btw. Copy/paste error? – Martin Tournoij Sep 07 '17 at 20:49
  • Yeah that was a typo. Very strange... I expect it to never enter the if, and it doesn't, but I'm not sure why the heck it's giving me an error... What OS/tcsh version are you using? I think we have an old version since it doesn't support the '$( )' syntax... – Kayson Sep 07 '17 at 22:08
  • No tcsh version supports the `$()` syntax; that only works in the Bourne shell. I use tcsh 6.20.00 on Linux. You can also try running it with `-x` to see some debug output, that might be helpful (`tcsh -x script.tcsh`). – Martin Tournoij Sep 07 '17 at 22:10
  • Ah my mistake. I'm on 6.17. I ran it with -x but its not much help. It shows how the if statement evaluates: `if ( != && != ) then` but I still get an error – Kayson Sep 07 '17 at 23:38
  • Turns out the problem is that I need an empty line at the end of the script... No idea why – Kayson Sep 08 '17 at 20:44
  • Hah, I know what the problem is with that. I'll add an answer. – Martin Tournoij Sep 08 '17 at 20:52

1 Answers1

4

The problem is that tcsh needs to have every line end in a newline, including the last line; it uses the newline as the "line termination character", and if it's missing it errors out.

You can use a hex editor/viewer to check if the file ends with a newline:

$ hexdump -C x.tcsh                                                  i:arch:21:49
00000000  69 66 20 28 22 78 22 20  3d 20 22 78 22 29 20 74  |if ("x" = "x") t|
00000010  68 65 6e 0a 09 65 63 68  6f 20 78 0a 65 6e 64 69  |hen..echo x.endi|
00000020  66                                                |f|

Here the last character if f (0x66), not a newline. A correct file has 0x0a as the last character (represented by a .):

$ hexdump -C x.tcsh    
00000000  69 66 20 28 22 78 22 20  3d 20 22 78 22 29 20 74  |if ("x" = "x") t|
00000010  68 65 6e 0a 09 65 63 68  6f 20 78 0a 65 6e 64 69  |hen..echo x.endi|
00000020  66 0a                                             |f.|

Ending the last line in a file with a newline is a common UNIX idiom, and some shell tools expect this. See What's the point in adding a new line to the end of a file? for some more info on this.

Most UNIX editors (such as Vim, Nano, Emacs, etc.) should do this by default, but some editors or IDEs don't do this by default, but almost all editors have a setting through which this can be enabled.

The best solution is to enable this setting in your editor. If you can't do this then adding a blank line at the end also solves your problem.

Martin Tournoij
  • 26,737
  • 24
  • 105
  • 146