2011-10-05 168 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