2010-06-21 85 views
3

失去了这个bash脚本串接的jar文件名到类路径(可变CP),while循环的值是正确的,但在子shell丢失在此相关的问题Bash variable scope变量值获取子shell

descibed
#!/bin/bash 
CP="AAA" 
func() { 
     ls -1 | while read JAR 
     do 
       if [ ! -z "$CP" ]; then 
         CP=${CP}':' 
       fi 
       CP=${CP}${JAR} 
     done 
     echo $CP # <-- prints AAA 
} 

func 

我的问题是,因为我不知道哪个元素是最后一个元素,所以如何保存这个值。

我是否真的必须将当前值(在循环中重复)保存到文件中?

编辑:

一位同事想出了其在这里工作得很好

ls | xargs echo|tr ' ' : 
+1

'echo * .jar | tr'':' – 2010-06-22 14:47:59

回答

6

的问题是,在管道中使用while创建一个子shell和子shell不能影响其父此命令序列。你可以通过几种方式解决这个问题。对于你现在在做什么,这样就足够了:

for JAR in *; do 
    # Your stuff 
done 

另一个要注意的是,你shouldn't rely on parsing ls

This还介绍了如何避免子shell。

1

您可能会发现使用查找更多功能。

例如:

当然
export CP=$(find /home/depesz/q/ -maxdepth 1 -type f -name '*.jar' -printf ':%p' | cut -b 2-) 

集的查找选项取决于你需要/想什么。

这是一个更接近你以前有什么:

export CP=$(find . -maxdepth 1 -type f -name '*.jar' -printf ':%f' | cut -b 2-) 
0

隐子shell是混乱的;总是使用圆括号将它们明确。要解决您的问题,只需在子shell中移动回显。

#!/bin/bash 
CP="AAA" 
func() { 
    ls -1 | (
    while read JAR 
    do 
     if [ ! -z "$CP" ]; then 
     CP=${CP}':' 
     fi 
     CP=${CP}${JAR} 
    done 
    echo $CP 
) 
} 
func 
+0

这实际上并不是特别有用,你所做的只是在函数退出前回显。 – 2017-11-13 16:39:11

0

这是另一种解决方案,它避免了一个子壳的产生。关键是要抓住回路输入到一个变量(在我的例子叫做“JARS”),然后这个变量重定向到使用循环< < EOF:

JARS=$(ls -1) 

while read JAR 
do 
     if [ ! -z "$CP" ]; then 
       CP=${CP}':' 
     fi 
     CP=${CP}${JAR} 
done <<EOF 
$JARS 
EOF 

echo $CP 
+1

评估'ls'的输出总是有问题的,如果路径包含空白等。 – 2012-05-18 00:51:41

0

这些答案似乎都不进入实际的返回正确的值,用一个非常简单的例程回应答案就可以了,但是说你想要脚本的输出,这是没用的。我没有最好的答案,但我没有太多时间弄清楚,所以我只是建议输出一个你想要的临时文件并读取它(惊讶它并没有提到日期):

#!/bin/bash 
CP="AAA" 
func() { 
    ls -1 | (
    while read JAR 
    do 
     if [ ! -z "$CP" ]; then 
     CP=${CP}':' 
     fi 
     CP=${CP}${JAR} 
    done 
    echo "$CP" > /tmp/cp-value-file 
) 
} 

func 
CP=$(cat /tmp/cp-value-file) 
echo $CP 

缺点:会在某些情况下需要写入磁盘循环的每次迭代。