如何从sh脚本运行csh脚本

时间:2014-01-28 18:30:21

标签: linux bash shell csh

我想知道是否有办法从sh脚本中获取csh脚本。以下是尝试实施的示例:

script1.sh:

#!/bin/sh

source script2

SCRIPT2:

#!/bin/csh -f

setenv TEST 1234
set path = /home/user/sandbox

当我运行sh script1.sh时,我得到了脚本2生成的语法错误(预计因为我们使用的是另一个Shebang)。有没有办法可以通过script1运行script2?

5 个答案:

答案 0 :(得分:5)

而不是source script2将其视为:

csh -f script2

答案 1 :(得分:2)

由于您的用例取决于保留csh脚本设置的环境变量,请尝试将其添加到script1的开头:

#!/bin/sh

if [ "$csh_executed" -ne 1 ]; then
    csh_executed=1 exec csh -c "source script2;
                                exec /bin/sh \"$0\" \"\$argv\"" "$@"
fi

# rest of script1

如果环境中的csh_executed变量未设置为1,请运行csh脚本script2,然后执行sh的实例,这将保留script2中对环境的更改。 exec用于避免为每个shell实例创建新进程,而只是从一个shell“切换”到另一个shell。在csh_executed命令的环境中设置csh可确保在script1实例重新执行csh时不会陷入循环。


不幸的是,有一个缺点,我认为不能修复,至少不是我对csh的有限知识:script1的第二次调用接收所有原始参数作为单个字符串,而不是一系列不同的参数。

答案 2 :(得分:1)

你不希望source在那里;它在现有shell中运行给定脚本,而不会生成子进程。显然,你的sh进程不能运行那些不是sh脚本的东西。

直接调用脚本,假设它是可执行的:

script2

答案 3 :(得分:0)

您最接近 sourcing 使用与原始脚本不同的执行程序的脚本的方法是使用execexec将使用新进程替换正在运行的进程空间。但是,与source不同,当您的exec编辑程序结束时,整个过程结束。所以你可以这样做:

#!/bin/sh

exec /path/to/csh/script

但你不能这样做:

#!/bin/sh

exec /path/to/csh/script
some-other-command

但是,您确定要确实脚本吗?也许你只想在子进程中运行它:

#!/bin/sh

csh -f /path/to/csh/script
some-other-command

答案 4 :(得分:0)

您希望csh脚本中的设置应用于调用它的sh脚本。

基本上,你不能这样做,尽管有一些(相当丑陋)的方法可以让它发挥作用。如果您执行您的csh脚本,它将在运行脚本的进程的上下文中设置这些变量;一旦它返回打电话,它们就会消失。

您最好的办法就是将新版本的csh脚本编写为sh脚本,并从调用sh脚本编写source.

您可以翻译您的csh脚本:

#!/bin/csh -f

setenv TEST 1234
set path = /home/user/sandbox

到此:

export TEST=1234
export PATH=/home/user/sandbox

(csh特别处理shell数组变量$path,将它绑定到环境变量$PATH。sh及其衍生物不会这样做,它们直接处理$PATH本身。 )

请注意,如果在顶部有一个#!行,那么打算获取源代码的脚本,因为在自己的进程中执行它是没有意义的;你需要在调用者的上下文中执行它的内容。

如果要保留脚本的两个副本,一个是来自csh或tcsh脚本的source d,另一个是来自sh / ksh / bash / zsh的source d或. ed脚本,不实用,还有其他解决方案。例如,您的脚本可以打印一系列要执行的sh命令;然后你可以做类似

的事情
eval `./foo.csh`

(行结尾会在这里造成一些问题)。

或者您可以修改csh脚本,以便设置所需的环境变量,然后调用一些指定的命令,这可能是一个新的交互式shell;这很不方便,因为它没有在你正在运行的交互式shell中设置这些变量。

如果软件包需要设置一些特殊的环境变量,通常的做法是提供称为setup.shsetup.csh的脚本,以便sh / ksh / bash / zsh用户可以做:

. /path/to/package/setup.sh

和csh / tcsh用户可以这样做:

source /path/to/package/setup.csh

顺便说一下,这个命令:

set path = /home/user/sandbox
您的示例脚本中的

可能不是一个好主意。它只用一个目录替换整个$PATH,这意味着除非指定完整路径,否则您将无法执行ls之类的简单命令。你通常想要这样的东西:

set path = ( $path /home/user/sandbox )

或者,在sh:

PATH=$PATH:/home/user/sandbox