2008-11-03 60 views
3
#!/bin/bash 

hello() 
{ 
    SRC=$1 
    DEST=$2 

    for IP in `cat /opt/ankit/configs/machine.configs` ; do 
     echo $SRC | grep '*' > /dev/null 
     if test `echo $?` -eq 0 ; then 
      for STAR in $SRC ; do 
       echo -en "$IP" 
       echo -en "\n\t ARG1=$STAR ARG2=$2\n\n" 
      done 
     else 
      echo -en "$IP" 
      echo -en "\n\t ARG1=$SRC ARG2=$DEST\n\n" 
     fi 
    done 
} 

hello $1 $2 

以上是我提供源代碼(SRC)& desitnation(DEST)路徑的shell腳本。當我沒有使用通配符''放入SRC路徑時,它工作正常。當我運行此shell腳本,並給予 '' 的.pdf或 '*',如下所示:如何正確處理bash shell腳本中的通配符擴展?

[email protected]:~/as_prac# ./test.sh /home/dev/Examples/*.pdf /ankit_test/as 

我得到以下輸出:

192.168.1.6 
ARG1=/home/dev/Examples/case_Contact.pdf ARG2=/home/dev/Examples/case_howard_county_library.pdf 

的DEST是/ ankit_test /但DEST還由於'*'而被修改。預期的答案是

ARG1=/home/dev/Examples/case_Contact.pdf ARG2=/ankit_test/as 

所以,如果你明白我在做什麼,請幫我解決這個BUG。 我會很感激你。

在此先感謝!

我需要知道我在程序中如何使用'* .pdf',而不會打擾DEST。

+0

嘿爲什麼一個下降??? – iankits 2008-11-03 12:02:14

回答

3

外殼將擴大通配符,除非你逃脫他們,因此,例如,如果你有

$ ls 
one.pdf two.pdf three.pdf 

和運行腳本

./test.sh *.pdf /ankit__test/as 

這將是一樣

./test.sh one.pdf two.pdf three.pdf /ankit__test/as 

這不是你所期望的。做

./test.sh \*.pdf /ankit__test/as 

應該工作。

+0

你是對的,但我想一一使用所有'one.pdf,two.pdf,three.pdf'。例如我需要將其全部複製到另一個位置。然後wat是解決方案。請幫助我。 – iankits 2008-11-03 09:51:23

1

你也錯過了最後的「完成」來關閉你的外循環。

0

有沒有必要產生一個shell來查看$?變量,你可以直接評估它。

應該僅僅是:

if [ $? -eq 0 ]; then 
+0

我沒有太多的exp。在shell腳本中。所以,不知道這是一種非常棒的使用方式。我也嘗試過你,但遇到了以下錯誤。 使用此錯誤時出現此錯誤 ./test.sh:第14行:[:缺少`]' – iankits 2008-11-03 10:14:07

4

你的腳本需要更多的工作。 即使轉義通配符後,也不會得到預期的答案。您將獲得:

ARG1=/home/dev/Examples/*.pdf ARG2=/ankit__test/as 

嘗試以下操作來代替:

for IP in `cat /opt/ankit/configs/machine.configs` 
do 
    for i in $SRC 
    do 
     echo -en "$IP" 
     echo -en "\n\t ARG1=$i ARG2=$DEST\n\n" 
    done 
done 

運行這樣的:

[email protected]:~/as_prac# ./test.sh "/home/dev/Examples/*.pdf" /ankit__test/as 
1

OK,這似乎做你想要什麼:

#!/bin/bash 

hello() { 

    SRC=$1 
    DEST=$2 

    while read IP ; do 
    for FILE in $SRC; do 
     echo -e "$IP" 
     echo -e "\tARG1=$FILE ARG2=$DEST\n" 
     done 
    done < /tmp/machine.configs 
} 

hello "$1" $2 
  1. 當您調用腳本時,仍然需要轉義任何通配符
  2. 當您調用hello函數時,必須使用雙引號,否則僅評估$1會導致通配符被擴展,但我們不希望發生,直到$SRC在功能
+0

p.s.這個版本只使用shell內建的,所以不需要產生任何子進程來完成它的工作。 – Alnitak 2008-11-03 10:48:58

2

分配。如果可以的話,改變傳遞給你的shell腳本參數的順序如下:

./test.sh /ankit_test/as /home/dev/Examples/*.pdf 

這將使你的生活,因爲容易得多可變部分移動到該行的末尾。接着,下面的腳本會做你想要什麼:

#!/bin/bash 
hello() 
{ 
    SRC=$1 
    DEST=$2 

    for IP in `cat /opt/ankit/configs/machine.configs` ; do 
     echo -en "$IP" 
     echo -en "\n\t ARG1=$SRC ARG2=$DEST\n\n" 
    done 
} 

arg2=$1 
shift 
while [[ "$1" != "" ]] ; do 
     hello $1 $arg2 
     shift 
done 
1

這就是我想出了:

#!/bin/bash 

hello() 
{ 
    # DEST will contain the last argument 
    eval DEST=\$$# 

    while [ $1 != $DEST ]; do 
     SRC=$1 

     for IP in `cat /opt/ankit/configs/machine.configs`; do 
      echo -en "$IP" 
      echo -en "\n\t ARG1=$SRC ARG2=$DEST\n\n" 
     done 

     shift || break 
    done 
} 

hello $* 

不是傳遞只有兩個參數的Hello()函數中,我們會通過在腳本得到的所有參數。

在hello()函數中,我們首先將最後一個參數賦值給DEST var。然後我們遍歷所有參數,將每個參數分配給SRC,並使用SRC和DEST參數運行我們想要的任何命令。請注意,如果包含空格,您可能需要在$ SRC和$ DEST周圍加引號。當SRC與DEST相同時,我們停止循環,因爲這意味着我們已經達到最終參數(目的地)。

0

您正在運行

./test.sh /home/dev/Examples/*.pdf /ankit_test/as 

和交互式外殼擴展通配符腳本得到它之前。你只需要引用的第一個參數,當你啓動它,在

./test.sh "/home/dev/Examples/*.pdf" /ankit_test/as 

,然後在你的腳本中,引用「$ SRC」任何地方,你硬是要使用通配符的事情(即,當你做echo $SRC ,而不是使用echo "$SRC"),並且當你想擴展通配符時不加引號。基本上,除非你想解釋元字符,否則總是在可能包含shell元字符的東西周圍加引號。 :)

1

對於使用通配符(如* .txt)的多個輸入文件,我發現此功能完美無缺,無需轉義。它應該像本地bash應用一樣工作,如「ls」或「rm」。這在任何地方都沒有記錄,因爲我花了3天的時間試圖找出答案,所以我決定將它發佈給未來的讀者。

目錄包含下列文件(LS的輸出)

file1.txt file2.txt file3.txt 

運行腳本像

$ ./script.sh *.txt 

甚至像

$ ./script.sh file{1..3}.txt 

腳本

#!/bin/bash 

# store default IFS, we need to temporarily change this 
sfi=$IFS 

#set IFS to $'\n\' - new line 
IFS=$'\n' 

if [[ -z [email protected] ]] 
    then 
    echo "Error: Missing required argument" 
    echo 
    exit 1 
fi 

# Put the file glob into an array 
file=("[email protected]") 

# Now loop through them 
for ((i=0 ; i < ${#file[*]} ; i++)); 
do 

    if [ -w ${file[$i]} ]; then 
    echo ${file[$i]} " writable" 
    else 
    echo ${file[$i]} " NOT writable" 
    fi 
done 

# Reset IFS to its default value 
IFS=$sfi 

輸出

file1.txt writable 
file2.txt writable 
file3.txt writable 

的關鍵是切換IFS(內部字段分隔符)暫時。您必須確保在切換之前將其存儲起來,然後在完成之後將其切換回來,如上所示。

現在您可以在文件[]數組中對擴展文件列表(,空格轉義爲)進行循環。我喜歡這個解決方案最好,最容易編程和最簡單的用戶。