简体   繁体   English

UNIX Shell脚本执行循环执行命令

[英]UNIX shell script do loop execute commands

In general I don't understand how to make most commands in a UNIX shell script do loop work the same as they work directly from the command line (using bash). 通常,我不理解如何使UNIX shell脚本中的大多数命令循环工作与直接从命令行(使用bash)工作一样。

As a simple test, a script called looping.sh to execute an SQL script (what's in filelist.txt doesn't matter in this case): 作为一个简单的测试,一个名为looping.sh的脚本可以执行一个SQL脚本(在这种情况下filelist.txt中的内容无关紧要):

for i in $(cat filelist.txt) 
do  $(sqlplus DB_USER/password@abc @test.sql) 
done

results in 结果是

looping.sh: line 2: SQL*Plus:: command not found looping.sh:第2行:找不到SQL * Plus ::命令

for each line in filelist.txt. 对于filelist.txt中的每一行。 Other variations on the 2nd line don't work, like putting it in quotes etc. 第二行的其他变体无效,例如将其放在引号中等。

Or, if filelist.txt has names of other sh scripts, let's say a single line in this case called_file1.sh and I want to execute it 或者,如果filelist.txt具有其他sh脚本的名称,那么在这种情况下, 假设一行名为_file1.sh ,我想执行它

for i in $(cat filelist.txt) 
do  exec $i
done

results in 结果是

: not found line 2: exec: called_file1.sh :找不到第2行:exec:named_file1.sh

The files are all in the same folder. 这些文件都在同一文件夹中。 I tried variations for the second line like /bin/sh $i , putting it in quotes and so on. 我尝试了第二行的变体,例如/ bin / sh $ i ,将其放在引号中,依此类推。 What's the magic way to execute a command in the do loop? 在do循环中执行命令的神奇方法是什么?

$(...) takes the contents and runs it as a command and then returns the output from the command. $(...)获取内容并将其作为命令运行,然后返回命令的输出。

So when you write: 所以当你写:

for i in $(cat filelist.txt) 
do  $(sqlplus DB_USER/password@abc @test.sql) 
done

what the shell does when it hits the body of the loop is run sqlplus DB_USER/password@abc @test.sql and then it takes the output from that command (whatever it may be) and replaces the $(...) bit with it. shell遇到循环主体时执行的操作是运行sqlplus DB_USER/password@abc @test.sql ,然后从该命令中获取输出 (无论它可能是什么),并将$(...)位替换为它。 So you end up with (not exactly since it happens again every loop but for sake of illustration) a loop that looks like this: 因此,您最终得到了一个循环(看起来不完全是因为每个循环都再次发生,但仅出于说明目的):

for i in $(cat filelist.txt) 
do  <output of 'sqlplus DB_USER/password@abc @test.sql' command>
done

and if that output isn't a valid shell command you are going to get an error. 如果该输出不是有效的shell命令,您将得到一个错误。

The solution there is to not do that. 那里的解决方案是不要这样做。 You don't want the wrapping $() there at all. 您根本不需要在其中包装$()

for i in $(cat filelist.txt) 
do  sqlplus DB_USER/password@abc @test.sql
done

In your second example: 在第二个示例中:

for i in $(cat filelist.txt) 
do  exec $i
done

you are telling the shell that the filename in $i is something that it should try to execute like a binary or executable shell script. 您告诉外壳程序$i中的文件名应该像二进制或可执行外壳程序脚本那样尝试执行。

In your case two things are happening here. 就您而言,这里正在发生两件事。 The filename in $i can't be found and (and this is harder to notice) the filename in $i contains a carriage-return at the end (probably a DOS line-ending file). 找不到$i的文件名, 并且 (这很难注意到) $i中的文件名在末尾包含一个回车符(可能是DOS行尾文件)。 (That's why the error message is a bit more confused then normal.) (I actually wonder about that since I wouldn't have expected that from an unquoted $i but from a quoted "$i" but I might just be wrong about that.) (这就是为什么错误消息比正常消息更混乱的原因。)(我实际上对此感到疑惑,因为我本来不希望在未$i引号的$i引号"$i"但我可能对此表示错误。)

So, for this case, you need to both strip the carriage-returns from the file (see point 1 of the "Before asking about problematic code" section of the tag info wiki for more about this) and then you need to make sure that filename is an executable script and you have the correct path to it. 因此,在这种情况下,您需要同时从文件中删除回车符(有关更多信息,请参见标签信息Wiki的“在询问有问题的代码之前”部分的第1点),然后需要确保该文件名是一个可执行脚本,您具有正确的路径。

Oh, also, exec never returns so that loop will only execute one file ever. 哦, exec也永远不会返回,因此循环只会执行一个文件。

If you want multiple executions then drop exec . 如果要多次执行,请删除exec

That all being said you Don't Read Lines With For . 话虽如此,你不会读For的台词 See Bash FAQ 001 for how to correctly (and safely) read lines from a file. 有关如何正确(安全地)从文件中读取行的信息,请参见Bash FAQ 001

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM