2013-06-23 57 views
1

我有一個bash腳本(cygwin),它使用一些帶有空格的窗口路徑。因此,我在我的變量定義中用\放棄了這個空間。腳本中的所有內容都能正常工作但是,我需要將此變量作爲參數傳遞給命令行可執行文件。當我這樣做時,我的逃跑變得混亂了。如何在傳遞給命令行參數時在bash中轉義變量

非樣本功能腳本:

$ bash -x test.sh 
+ destinationPath='/cygdrive/c/Documents and Settings/Eric/My Documents/' 
+ attachments='\n2013-12-12.pdf' 
+ body='Test Body' 
+ [email protected] 
+ args= 
+ for file in '$attachments' 
+ file=2013-12-12.pdf 
+ touch 2013-12-12.pdf 
+ mv 2013-12-12.pdf '/cygdrive/c/Documents and Settings/Eric/My Documents//2013-12-12.pdf' 
mv: listing attributes of `2013-12-12.pdf': Invalid argument 
+ args=' -a /cygdrive/c/Documents and Settings/Eric/My Documents//2013-12-12.pdf' 
+ echo -e Test Body 
+ email --from-addr [email protected] --from-name 'Automated CSS Downloader' --subject 'Downloaded new file(s) from CSS' -a /cygdrive/c/Documents and Settings/Eric/My Documents//2013-12-12.pdf [email protected] 
email: WARNING: Email address 'and' is invalid. Skipping... 
email: FATAL: Could not open attachment: /cygdrive/c/Documents: No such file or directory 

所以,你可以看到在路轉義空間沒有被出口在$ args變量:從腳本

#!/bin/sh                                 

# file paths                                
destinationPath="/cygdrive/c/Documents and Settings/Eric/My Documents/" 
attachments="\n2013-12-12.pdf" 
body="Test Body" 
recipient="[email protected]" 


     # prepare attachments                            
     args="" 
     for file in $attachments ; do 
      file=${file//[ \\n]/} 
      touch $file 
      mv $file "$destinationPath/$file" 
      args="$args -a $destinationPath/$file" 
     done 

     # send email                              
     echo -e $body | email --from-addr [email protected] --from-name "Automated CSS Downloader" --subject "Downloaded new file(s) \ 
from CSS" $args [email protected] 

輸出。我假設錯誤出現在「args = ...」行上。但我不確定如何轉義$ destinationPath以確保轉義字符得以保留。

我試過在destinationPath中使用雙引號(沒有轉義空格),但無濟於事。如果我嘗試在args =行中雙引號$ destinationPath,那麼輸出結果也會被一堆額外的引用搞砸。

我該如何得到這個工作?我嘗試過使用$ IFS變量,但我真的不知道自己在做什麼,並且似乎也無法使用它,儘管我懷疑該解決方案與某些方面有關$ IFS。

+0

你試過雙逃脫的空間?例如。'Documents \\\ and \\'' –

+0

我曾嘗試過,但遇到了幾個問題:1)我的mv不工作,因爲它試圖將文件移動到Documents \\和\\(即: bash吞下一次逃跑),並且在電子郵件表達式中擴展$ args然後變成:-a'/ cygdrive/c/Documents \'和'Settings \ Eric \ My \'Documents/AJ/CSS // 2013 -06-21.pdf。在每個空間裏,這都不起作用。 –

+0

也許你可以將destinationPath加入雙引號並刪除轉義空格?和你一樣休息 – robson

回答

5

有這樣做沒有一個數組的沒有什麼好辦法。 (有這樣做,用eval的不是好辦法,但數組是簡單的。)

的問題是,你希望每個文件,以最終成爲一個參數email,但你要對所有這些參數聚集成一個bash變量。有沒有辦法做到這一點:你可以使bash變量作爲單個參數插入("$arg"),或者你可以使它被插入,因爲它被分成多個單詞($arg),但是你不能得到它根據是否在創建變量時轉義空格來拆分,因爲bash只記住分配給變量的字符串,而不是轉義符。

但是,你可以用一個數組來做到這一點,因爲你可以讓每個文件名只有一個數組元素,並且你可以讓bash插入一個數組作爲每個元素的一個參數。

方法如下:

# file paths                                
destinationPath="/cygdrive/c/Documents and Settings/Eric/My Documents/" 
attachments="\n2013-12-12.pdf" 
body="Test Body" 
recipient="[email protected]" 


# prepare attachments                            
args=() 
for file in $attachments ; do 
    file=${file//[ \\n]/} 
    touch $file 
    mv $file "$destinationPath/$file" 
    args+=(-a "$destinationPath/$file") 
done 

# send email                              
echo -e $body | 
    email --from-addr [email protected] \ 
     --from-name "Automated CSS Downloader" \ 
     --subject "Downloaded new file(s) from CSS" \ 
     "${args[@]}" [email protected] 

您也可能想使attachments變量到一個數組;從換行符的存在,我假設你實際上以更復雜的方式設置它,所以我沒有更改代碼。但是,如果附件名稱中有一個空格,那麼當前的代碼將不起作用(並且我非常肯定,for表單中的參數擴展將消除換行符,除非您已更改$IFS的值,所以file=${file//[ \\n]/}不應該是必需的。)

+0

+1 @Er​​icB。你需要一個數組:http://mywiki.wooledge.org/BashFAQ/050 –

+0

謝謝。會放棄一下。我不知道/意識到Bash支持數組。至於使附件成爲一個數組,我非常喜歡,但我需要將它擴展到我的電子郵件正文中,每個附件名稱一行。將研究如何使這項工作輕鬆。 –

+0

優秀。像魅力一樣工作!需要學習如何在Bash中更好地使用數組。謝謝! –

0

在字符串中提供destinationPath時,您需要使用雙引號。

這應該工作:

#!/bin/sh                                 

# file paths                                
destinationPath="/cygdrive/c/Documents and Settings/Eric/My Documents/" 
attachments="\n2013-12-12.pdf" 
body="Test Body" 
recipient="[email protected]" 


     # prepare attachments                            
     args="" 
     for file in $attachments ; do 
      file=${file//[ \\n]/} 
      touch $file 
      mv $file "$destinationPath/$file" 
      #HERE YOU NEED ESCAPED DOUBLEQUOTED 
      args="$args -a \"$destinationPath/$file\"" 
     done 

     # send email                              
     echo -e $body | email --from-addr [email protected] --from-name "Automated CSS Downloader" --subject "Downloaded new file(s) \ 
from CSS" $args [email protected] 
+0

這是行不通的,因爲bash在替換變量之前確實使用了escape和quote解釋,所以如果你把escapes/quotes/etc *放在*變量中,它們永遠不會生效(到變量被擴展的時候,它們爲時已晚做任何事)。數組(如@ rici的答案)是做這種事情的最好方法。 –

相關問題