2012-12-24 23 views
0

當我運行此腳本:我寫這個劇本,但它好像我錯過了一些語法

#!/bin/bash 
#This script distributes file/folders to all POP servers within the production environment. 
echo "Are you willing to transfer a file or a directory? [Answer: file/dir]" 
read answer 
echo "Please enter a file name or a full path to the files/directories you want to distribute" 
read locfile 
echo "Please enter the destination path" 
read destfile 
if [-n $answer] then 
     case "$answer" in 
       file) 
         for srv in `cat ~/srv.lst`; 
         do echo "$srv:"; 
         /usr/bin/scp $locfile $srv:$destfile; 
         done 
       ;; 
       dir) 
         for srv in `cat ~/srv.lst`; 
         do echo "$srv:"; 
         /usr/bin/scp -r $locfile $srv:$destfile; 
         done 
       ;; 
       *) 
       echo "Please check your input" 
esac 
fi 

我得到這樣的輸出:

./distribute_files: line 26: syntax error near unexpected token `fi' 
./distribute_files: line 26: `fi' 

我已經試過有或沒有其他人,但我似乎無法找到問題。 感謝

回答

3

我重寫使用bash成語腳本:

#!/bin/bash 

#This script distributes file/folders to all POP servers within the production environment. 

echo "Are you willing to transfer a file or a directory? [Answer: file/dir]" 
read -r answer 
echo "Please enter a file name or a full path to the files/directories you want to distribute" 
read -r locfile 
echo "Please enter the destination path" 
read -r destfile 

if [[ -n "$answer" ]] then 
    case "$answer" in 
     file) 
      while read -r srv; do 
       [[ -n "$srv" ]] || continue 
       echo "$srv:" 
       /usr/bin/scp -- "$locfile" "$srv:$destfile" 
      done < ~/srv.lst 
      ;; 
     dir) 
      while read -r srv; do 
       [[ -n "$srv" ]] || continue 
       echo "$srv:" 
       /usr/bin/scp -r -- "$locfile" "$srv:$destfile" 
      done < ~/srv.lst 
      ;; 
     *) 
      echo "Please check your input" 
      ;; 
    esac 
fi 

發生了什麼變化?更多的引用(當文件名包含空格時,你的腳本早晚會破壞),並且使用[[...]]而不是棄用的和不太可靠的(在bash中)[...]。我還使用read-r選項(因爲不允許反斜槓轉義任何字符)。我也改變了

for svr in `cat ~/srv.lst`; do 

進入比較成熟的

while read -r srv; do 
    ... 
done < ~/src.lst 

(它真的認爲非常不好的bash實踐遍歷一個cat像你一樣)。我不得不包括一個後衛[[ -n "$srv" ]]來忽略空行。在這裏,你可以用一個連字符添加的東西,如果要處理意見更復雜......

我還添加了--scp,以防萬一文件$locfile開始。這會混淆scp(它會認爲這是一個選項)。這被認爲是非常好的外殼練習。

我以爲我會這樣做,正如你提到的生產環境。 (我經常害怕看到生產中使用的腳本)。

事實上,你的問題是關於這裏沒有需要[...],你可以放心地包含到case爲:

#!/bin/bash 

#This script distributes file/folders to all POP servers within the production environment. 

echo "Are you willing to transfer a file or a directory? [Answer: file/dir]" 
read -r answer 
echo "Please enter a file name or a full path to the files/directories you want to distribute" 
read -r locfile 
echo "Please enter the destination path" 
read -r destfile 

case "$answer" in 
    "") 
     true 
     # Do whatever you like here 
     ;; 
    file) 
     while read -r srv; do 
      [[ -n "$srv" ]] || continue 
      echo "$srv:" 
      /usr/bin/scp -- "$locfile" "$srv:$destfile" 
     done < ~/srv.lst 
     ;; 
    dir) 
     while read -r srv; do 
      [[ -n "$srv" ]] || continue 
      echo "$srv:" 
      /usr/bin/scp -r -- "$locfile" "$srv:$destfile" 
     done < ~/srv.lst 
     ;; 
    *) 
     echo "Please check your input" 
     ;; 
esac 

而且,像你這樣的「互動」的劇本被認爲是不好的做法(這是否讓人聯想到舊式家庭計算機上的舊BASIC程序?)。您應該考慮在腳本中使用參數(向讀者行使權限)。

你可以完全擺脫dir vs.s。文件的東西,通過測試$locfile是否是一個目錄。而擺脫了echo,告訴哪個文件是scp ING使用-v(詳細)選項:

#!/bin/bash 

#This script distributes file/folders to all POP servers within the production environment. 

read -r -p "Please enter a file name or a full path to the files/directories you want to distribute" locfile 
read -r -p "Please enter the destination path" destfile 

ropt="" 
if [[ -d "$locfile" ]]; then 
    ropt='r' 
fi 

while read -r srv; do 
    [[ -n "$srv" ]] && /usr/bin/scp -v$ropt -- "$locfile" "$srv:$destfile" 
done < ~/srv.lst 

事實上,更多的我看你的腳本做什麼,我越覺得它的速度更快了用戶在終端中輸入:

$ while read -r srv; do [[ -n "$srv" ]] && /usr/bin/scp -v "myfile" "$srv:mydestfile"; done < ~/srv.lst 

(因爲她就可以使用文件名完成用製表符),而不是調用你的腳本。

希望這會有所幫助!

+0

嗯,首先感謝您的反饋,非常感謝,我期待明天在工作中更改我的腳本。第二,這一切都是從一開始就把它寫在一行中,甚至不需要腳本,但目前,我的團隊中沒有人知道Linux,這只是爲了讓他們的事情更容易,以防萬一我無法使用。 反正,非常感謝所有這些信息! –

2

而不是

if [-n $answer] then 

嘗試

if [ -n $answer ] 
then 

也就是說在括號,使用空間,並把then在另一條線路。

+0

上解決了這個問題,可以請你告訴我有什麼區別? –

+0

@ItaiGanot空格是在bash中指定一個條件語句。另外,'if'行必須在'then'之前終止,所以要麼使用分號,要麼將'then'放在單獨的行中。這兩種都只是殼中的怪癖。 – chrisaycock

+0

@ItaiGanot殼中沒有怪癖。當你編寫'if [-n $ answer] then'時,bash將嘗試執行'[-n']參數(擴展名)'$ answer'和'then',這不是你想要的。相反,你需要'if [-n「$ answer」]; then'。但看到我的答案進一步(好)的選擇。 –

1

[是一個命令,所以你需要尊重空白:

if [ -n $answer ]; then 

就像cat-n fileecho-e foo無效。

$ which [ 
/usr/bin/[ 
+0

''這裏''不相關,因爲(在bash中)'''是內建的,你可以用'type ['快速檢查。 –

+1

那麼,即使內置插件是命令,不是嗎?指出'['不是語法糖,而是像其他任何命令或內置命令一樣,這是一件好事。 – Jens

1

除此之外,總是給你的shell變量test -n,所以用if [ -n "$answer" ]; then代替。

3

相反的:

if [-n $answer] then 

後使用 '[' 和之前 ']' 空白。如果你想在同一行中使用;使用「那麼」:

if [ -n $answer ]; then 

或者:

if [ -n "$answer" ] 
then 
相關問題