2011-10-13 181 views
1

我有一個腳本:bash腳本參數擴展

#!/bin/bash 
SINGLE_FILE=/tmp/blah.file 
MULTIPLE_FILES=/tmp/{dir1,dir2}/*.file 

cp $SINGLE_FILE $MULTIPLE_FILES /tmp/newDir 

這將失敗:

CP:不能STAT`/tmp/{dir1,dir2}/*.file':無這樣的文件或目錄

它看起來像腳本沒有擴大我的變量通配符。所以我可以使這個腳本工作:

eval cp $SINGLE_FILE $MULTIPLE_FILES /tmp/newDir 

我的問題是:爲什麼腳本沒有擴大我的變量在第一位?另外,除了使用eval之外,還有其他解決方法嗎?

回答

3

腳本將您的變量擴展到您設置的值,即/tmp/{dir1,dir2}/*.file,對吧?

正如您已經正確發現的那樣,您需要讓shell'再次運行該行'並重新評估您在其中找到的任何變量。

所以,除了EVAL沒有其他方法(當然,你可以子shell的東西,浪費了大量的處理能力,而且基本上翻拍的eval用自己的代碼的功能。)

我可以推薦的唯一的事情就是使用shell調試功能set -vx自己看看它是如何工作的,即

$set -vx 
set -vx 
>set -vx 
$SINGLE_FILE=/tmp/blah.file 
SINGLE_FILE=/tmp/blah.file 
>SINGLE_FILE=/tmp/blah.file 

$MULTIPLE_FILES=/tmp/{dir1,dir2}/*.file 
MULTIPLE_FILES=/tmp/{dir1,dir2}/*.file 
>MULTIPLE_FILES='/tmp/{dir1,dir2}/*.file' 

$echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir 
echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir 
>echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir 
/tmp/blah.file /tmp/{dir1,dir2}/*.file /tmp/newDir 

$eval echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir 
eval echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir 
>eval echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir 
echo /tmp/blah.file /tmp/{dir1,dir2}/*.file /tmp/newDir 
>echo /tmp/blah.file '/tmp/dir1/*.file' '/tmp/dir2/*.file' /tmp/newDir 
/tmp/blah.file /tmp/dir1/*.file /tmp/dir2/*.file /tmp/newDir 
+0

我從來不知道 '設置-vx',謝謝! –

2

看來,這是令人困惑的事情在這裏的括號。國際海事組織,這種不一致是shell中的一個錯誤 - 如果你有MULTIPLE_FILES=/tmp/dir1/*.file,它會立即擴展。添加大括號,然後停止嘗試展開。當你運行其他任何東西時,這是不同的。

與此同時,eval不是一個壞解決方案/解決方法在這裏。我唯一能想到的就是MULTIPLE_FILES=$(echo /tmp/{dir1,dir2}/*.file),這不一定更好。

一般來說,我試圖避免這種類型的事情,因爲當空間在文件/目錄名稱中時,適當的shell解析是困難的。相反,我儘量使用find ... -print0 | xargs -0 ...。或直接進入另一種腳本語言,如Perl。

1

你可以使用一個數組:

SINGLE_FILE=/tmp/blah.file 
MULTIPLE_FILES=(/tmp/{dir1,dir2}/*.file) 
cp -t /tmp/newDir "$SINGLE_FILE" "${MULTIPLE_FILES[@]}" 
+0

我知道必須有一個聰明的方法來使用這個數組......謝謝 –