我想设置一个指示目录的变量,并使用它来访问该目录中的文件 所以我写了一个简单的脚本(注意我没有把#!/ bin / csh放在前面)
文件测试:
set dir1=/tmp
ls -l $dir1
我做了chmod +x test
并运行了test
,但它只显示我当前的目录,如$ dir1只是null。我尝试使用{XX}无济于事。
我想在没有usig#!/ usr / bin / env tcsh或#!/ bin / csch或#!/ bin / tcsh的情况下这样做。这不可能吗? (我不想启动新的shell但使用相同的别名和其他先前的环境变量等。)
有什么问题?我在tcsh中这样做。
我后来发现了
dir1=/tmp
ls $dir1
就是答案。
答案 0 :(得分:3)
注意 shell变量之间的区别,它可以交互使用或在脚本中使用但是对于脚本是本地的,而环境变量则成为传递的环境的一部分到脚本调用的程序。
在POSIX(或bash或相关)shell中,您可以使用export
内置命令将shell变量转换为环境变量。
在csh / tcsh中,set
命令设置shell变量,但setenv
命令设置环境变量。设置完成后,您可以像shell变量一样在shell脚本中使用环境变量,但该变量将包含在子shell或您运行的其他程序的环境中。
注意:
1% set foo=bar
2% echo $foo
bar
3% csh
1% echo $foo
foo: Undefined variable.
2%
VS
1% setenv foo bar
2% echo $foo
bar
3% csh
1% echo $foo
bar
2%
在第一个示例中,set
命令创建了一个shell变量,该变量仅在设置它的shell的上下文中可见。在第二个示例中,setenv
命令创建了一个传递给子shell的 environment 变量。
请注意,通过脚本中的任何方法设置变量将不允许将该变量传递回调用shell,就像使用使用花括号的POSIX shell函数一样。对于csh / tcsh中的那种功能,您可能不得不依赖alias
命令。例如,我使用以下别名:
alias go 'cd `dirname \!:*`'
让我这样做:
1% alias go 'cd `dirname \!:*`'
2% go /usr/local/etc/foo.rc
3% pwd
/usr/local/etc
4%
查看History substitution
的{{1}}部分,了解其工作原理。
如果您正在尝试构建依赖于传递回父shell的信息的解决方案,请使用不同的shell,或者对您编写的命令使用stdout的反引号替换以及别名。
答案 1 :(得分:2)
简短回答:根据您的评论,您需要使用source
命令运行脚本(请参阅@ ghoti的文章)。
答案很长:有许多不同的方法来运行shell脚本,对它的运行方式有不同的影响。
运行脚本的正常首选方法是让脚本以shebang(#!
)行开头,指定要用于它的解释器(/ bin / sh,/ bin / bash等) ),然后将脚本放在路径中的目录中并按名称执行,或者将脚本的路径指定为命令(请注意./scriptname
是此特殊情况,其中路径为“就在这里“)。
使用此方法,将创建运行指定解释器的子进程并执行该脚本。由于脚本在子进程中执行,因此设置的环境变量之类的东西不会影响它运行的shell的环境(即设置dir1=/tmp
仅适用于脚本,而不是在脚本完成后。)
如果脚本没有shebang,您也可以按名称或路径运行脚本。这也创建了一个运行一些解释器的子进程(其中一个是一个crapshoot)。这样做是没有充分理由的;使用shebang。
您可以通过显式调用解释器来运行脚本,如sh /path/to/script
,bash /path/to/script
或csh /path/to/script
。请注意,如果脚本位于当前目录中,则不需要完整路径;它的名字就足够了。这也在子进程中运行脚本,但使用指定的解释器(如果有的话,忽略shebang行)。
如果您指定了错误的解释器(例如,对于使用仅使用bash的功能的脚本使用sh
),这个有时会造成麻烦,并且只有在某些东西阻止您使用第一个选项时才应该使用它。
最后,您可以使用source
命令运行脚本(例如source /path/to/script
或source scriptname
,如果它在当前目录中)。与其他人不同,这不会创建子流程;它告诉当前shell从文件中执行命令。这意味着最好用当前shell的正确语法编写脚本;如果你从csh或tcsh {b}或sh脚本source
,它就不会顺利。这也意味着shebang(如果有的话)会被忽略。
如果您希望脚本中的环境变量定义在您运行脚本的shell中可用,则这是唯一的方法。 (好吧,除了类似sh的shell,你可以使用.
命令,因为这是source
的同义词。)
由于脚本为source
d时会忽略任何shebang行,因此您可以包含它。我倾向于将一个shebang添加到应该是源d, either giving the correct interpreter as a hint to users, or using a
#!/ bin / echo shebang to print a message if someone tries to run the script without
source`的脚本中:
#!/bin/echo source this script from csh: source
...这是一种黑客攻击,因为/bin/echo
不是解释者;但它会运行命令/bin/echo source this script from csh: source /path/to/script
,它至少指向用户正确的方向。请注意,这并不能防止有人使用sh
,bash
等来覆盖shebang。
set
在类似于类似于csh的shell中做了完全不同的事情。在类似csh的shell中,您使用set var=value
分配变量,但在类似sh的shell set
中设置脚本的位置参数($1
,$2
等),因此{ {1}}将set var=value
设置为字符串“var = value”。另外,在你的回答中,你使用$1
命令 - 这根本不是一个unix命令,它是一个DOS命令;这表明你在Windows下运行这些脚本,在这种情况下潜伏着另外一类潜在的兼容性混淆。
答案 2 :(得分:1)
您应该将shebang添加到脚本中以强制使用tcsh 否则将使用默认shell! 并且您的变量定义/赋值语法可能无法按预期工作!
将以下第一行添加到您的脚本
#!/usr/bin/env tcsh