簡體   English   中英

如何在bash shell腳本中正確處理通配符擴展?

[英]How to properly handle wildcard expansion in a bash shell script?

#!/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或'*'時,如下所示:

root@ankit1:~/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 / as,但由於'*',DEST也會被刪除。 預期的答案是

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

所以,如果你了解我想要做什么,請幫助我解決這個問題。 我會感激你的。

提前致謝!!!

我需要確切地知道我如何在我的程序中逐一使用'* .pdf'而不會打擾DEST。

您的腳本需要更多工作。 即使在逃避通配符后,您也無法獲得預期的答案。 你會得到:

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

像這樣運行:

root@ankit1:~/as_prac# ./test.sh "/home/dev/Examples/*.pdf" /ankit__test/as

shell將擴展通配符,除非你將它們轉義,例如,如果你有

$ 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

應該管用。

如果可以,請更改傳遞給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

對於使用通配符(如* .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 $@ ]]
  then
  echo "Error: Missing required argument"
  echo
  exit 1
fi

# Put the file glob into an array
file=("$@")

# 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(內部字段分隔符)。 您必須確保在切換之前存儲它,然后在完成之后將其切換回來,如上所示。

現在,您在文件[]數組中有一個擴展文件列表( 帶有空格轉義 ),然后您可以循環遍歷。 我喜歡這個解決方案最好,最容易為用戶編程和最簡單。

你也錯過了最后的“完成”以關閉你的外部for循環。

好的,這似乎做你想要的:

#!/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之前發生這種情況。

這是我想出的:

#!/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相同時,我們停止循環,因為這意味着我們已經達到最終參數(目標)。

你在跑

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

並且您的交互式shell在腳本獲取之前擴展通配符。 你只需要在啟動它時引用第一個參數,如

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

然后,在你的腳本中,引用“$ SRC”,你真正想要帶有通配符的東西(例如,當你做echo $SRC ,而是使用echo "$SRC" )並在你想要擴展通配符時不加引號。 基本上,除非您希望解釋元字符,否則始終在可能包含shell元字符的內容周圍加上引號。 :)

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

它應該只是:

if [ $? -eq 0 ]; then

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM