0

I am running the following command though a Python script:

tcsh -c 'cmd1 && cmd2 && cmd3 && cmd4'

Only the first command is getting executed or the first two commands are getting executed. How do I make sure all the commands are executed? The first command will source env variables.

Tried login shell '-tcsh' instead of 'tcsh'. I also tried removing 'exit 0' from the scripts that are run though the commands.

4
  • 2
    cmd1 && cmd2 executes cmd2 only if cms1 had success, are you sure at least cmd1 cmd2 and cmd3 success ? Else replace &&by ; to do all commands in all cases. The first command will source env variables except if cmd1 is something like source <file> the new env is lost at the end of cmd1 Commented Oct 13 at 10:22
  • sooo tcsh -c 'cmd1; cmd2; cmd3; cmd4'? Commented Oct 13 at 10:23
  • 5
    You forgot to show the Python code that you're using. Do you understand what && means in that context? Does each command (left to right) depend on the previous one? If not, have you considered running them in parallel? Commented Oct 13 at 11:02
  • BTW, if the problem still happens with tcsh -c 'cmd1 && cmd2 && cmd3 && cmd4' run from your shell and no Python involved anywhere, it shouldn't be tagged Python at all. Commented Oct 13 at 12:12

2 Answers 2

2

tcsh doesn’t support && in non-interactive mode (like when using -c), so only the first command runs.

Use semicolons instead:

tcsh -c 'cmd1; cmd2; cmd3; cmd4'

Or, if the first command sets environment variables:

tcsh -c 'source /path/to/env.csh; cmd2; cmd3; cmd4'

If you need all commands to share the same environment, put them in a .tcsh script and run that instead.

Sign up to request clarification or add additional context in comments.

4 Comments

When using semicolon, is there a conditional dependency (left to right)? i.e., if cmd1 returns non-zero, will cmd2 execute?
No, with semicolons (;) in tcsh, commands run sequentially regardless of success or failure. If cmd1 fails (non-zero exit status), cmd2 will still run.
You'll see in the OP "I also tried removing 'exit 0' " which I interpret as meaning that execution should be conditional. After all, at the command line, that's exactly what the double-ampersand would mean. Therefore, your "solution" is flawed.
If you need conditional execution (like &&), semicolons won’t do it. In tcsh, you’d need to check $status manually, for example: tcsh -c 'cmd1; if ($status == 0) cmd2' for a case like this to make it neater you can put it into a tcsh script fullcommand.tcsh will look like this cmd1 ``` if ($status == 0) then cmd2 if ($status == 0) then cmd3 if ($status == 0) then cmd4 endif endif endif ``` and then you run it with tcsh fullcommand.tcsh
0

Your use of the double-ampersand implies that execution should be conditional - i.e., working from left to right the most recently executed command should terminate normally before attempting the next command.

You'll need to do this using a loop.

In the code below you'll need to adjust the COMMANDS list to suit your environment then:

import subprocess
from pathlib import Path

COMMANDS = [Path(f"~/temp/{cmd}")for cmd in ("cmd1", "cmd2", "cmd3", "cmd4")]

for command in COMMANDS:
    if subprocess.run(["tcsh", str(command.expanduser())]).returncode != 0:
        print(f"Command {command} failed. Stopping")
        break

8 Comments

This won't work either because each of the commands runs in an entirely separate and new process. So the things that are sourced in the first command will not be available in subsequent commands.
@MarkSetchell Of course you're right. I don't understand how environment variables sourced in cmd1 would be applicable to subsequent scripts anyway. Can you explain how one might do that?
When sourced, the environment variables in the script are set in the process that sources them. However, in your code, that process then finishes and you then start a new one in the next iteration of the for loop.
@MarkSetchell It seems to me that if tcsh -c 'cmd1 && cmd2 && cmd3 && cmd4' is executed (command line) that environment variables sourced via cmd1 would not be available to cmd2. What am I missing?
OP says in their question that first command sources some variables, so I'm guessing cmd1= source something
@MarkSetchell Sure, I get that but I don't see how sourcing in cmd1 would make sourced variables available in cmd2. That's what I'm trying to understand
Try it. Define a variable in a script and source it, then check your environment.
@MarkSetchell I did. It doesn't work

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.