2011-10-05 130 views
-1

我学习的东西越多,我的问题就越多,而我越理解为什么很少有人做bash。简单是别的,但我喜欢它。Bash远程文件系统目录test

我已经设法弄清楚如何测试目录和那里writablity,但有一个问题,我试图通过ssh远程服务器做到这一点。测试/ tmp目录的第一个实例工作正常,但当第二部分被调用时,我得到line 0: [: missing]'

现在,如果我用单引号替换\“,它的工作原理,但我认为单引号把变量引用的?有人可以解释这对我好吗?假设tmp目录确实存在并且是可写的,这里的脚本到目前为止

#!/bin/bash 
SshHost="hostname" 
SshRsa="~/.ssh/id_rsa" 
SshUser="user" 
SshPort="22" 
Base="/tmp" 
Sub="one space/another space" 

BaseBashExist="bash -c \"[ -d \"$Base\" ] && echo 0 && exit 0 || echo 1 && exit 1\"" 
SSHBaseExist=$(ssh -l $SshUser -i $SshRsa -p $SshPort $SshHost ${BaseBashExist}) 
echo -n $Base 
if [ $? -eq 0 ] 
    then 
     echo -n "...OK..." 
    else 
     echo "...FAIL" 
     exit 1 
fi 
BaseBashPerm="bash -c \"[ -w \"$Base\" ] && echo 0 && exit 0 || echo 1 && exit 1\"" 
SSHBaseExist=$(ssh -l $SshUser -i $SshRsa -p $SshPort $SshHost ${BaseBashPerm}) 
if [ $? -eq 0 ] 
    then 
     echo "...writeable" 
    else 
     echo "...not writeable" 
fi 

BaseAndSub="$Base/$Sub" 
BaseAndSubBashExist="bash -c \"[ -d \"$BaseAndSub\" ] && echo 0 && exit 0 || echo 1 && exit 1\"" 
SSHBaseAndSubExist=$(ssh -l $SshUser -i $SshRsa -p $SshPort $SshHost ${BaseAndSubBashExist}) 
echo -n $BaseAndSub 
if [ $? -eq 0 ] 
    then 
     echo -n "...OK..." 
    else 
     echo "...FAIL" 
     exit 1 
fi 
BaseAndSubBashPerm="bash -c \"[ -w \"$BaseAndSub\" ] && echo 0 && exit 0 || echo 1 && exit 1\"" 
SSHBaseAndSubPerm=$( ssh -l $SshUser -i $SshRsa -p $SshPort $SshHost ${BaseAndSubBashPerm}) 
if [ $? -eq 0 ] 
    then 
     echo -n "...writeable" 
    else 
     echo "...not writeable" 
fi 
exit 0 
+0

你是什么意思“很少有人这样做”?诚然,很少有人做得很好,但这完全是另一个话题。 – tripleee

+0

没有冒犯的意图,只是在15年的发展中,我真的只有一个人,其实真正知道bash的人...... –

回答

1

你在这方面用单引号很好;在远程bash看到脚本的时候,你的本地bash已经替换了你想要替换的变量。

但是,你的脚本是一团糟。如果不能大幅简化它,你应该把重复的代码放在函数中。

#!/bin/bash 

remote() { 
    # most of the parameters here are at their default values; 
    # why do you feel you need to specify them? 
    #ssh -l "user" -i ~/.ssh/id_rsa -p 22 hostname "[email protected]" 
    ssh hostname "[email protected]" 
    # —---------^ 
    # if you really actually need to wrap the remote 
    # commands in bash -c "..." then add that here 
} 

exists_and_writable() { 
    echo -n "$1" 

    if remote test -d "$1"; then 
     echo -n "...OK..." 
    else 
     echo "...FAIL" 
     exit 1 
    fi 

    if remote test -w "$1"; then 
     echo "...writeable" 
    else 
     echo "...not writeable" 
    fi 
} 

Base="/tmp" 
# Note the need for additional quoting here 
Sub="one\\ space/another\\ space" 

exists_and_writable "$Base" 

BaseAndSub="$Base/$Sub" 

exist_and_writable "$BaseAndSub" 

exit 0 
+0

为文件测试添加一个函数可以节省将近35%的代码,而且它仍然很简单。 –

+0

另请注意'ssh'的退出码是来自远程命令的退出码。整个&& echo 0 ||回声1'你的东西是多余的。 – tripleee

+0

回声的原因是让我有一个局部变量来测试事实。这将允许我在执行多个目录测试之后执行全局测试。如果这是有道理的,但是在您接近的情况下,不需要进行本地变量测试 –

2

你应该做的第一件事就是重构你的代码记住简单,那么引用错误也会消失。尝试:

if ssh [flags] test -w "'$file'"; then 

将SSH标志封装在ssh配置中以方便重用,并且脚本将显着缩短。

+0

+1和远程'bash -c“命令”'调用的同上。有些情况下,你真的需要在远程主机上运行Bash而不是常规登录shell,但我强烈推测这不是这种情况之一。 – tripleee

+0

封装标志,只需双引号'$ file'确实节省了大约20%的代码,并大大简化了结构...感谢您的输入。 **我可以假设双引号内的单引号不会妨碍变量引用**,这与文档中所说的相反。 –

+0

尝试'echo'foo'$ HOME'“'并思考一段时间。单引号在双引号内不是特殊的。 – tripleee