2010-10-29 47 views
1

我已經設法湊齊下面的腳本,將文件從一個Samba共享移動到另一個。它似乎適用於所有合法的Windows文件名,除非文件名中有美元字符($)。典型的文件名失敗是:〜$ file.doc

任何幫助,將不勝感激。

#!/bin/bash 
# Script to move old files from public to quarantine 

srcbase=/net/public 
destbase=/net/quarantine 
logfile=$srcbase/moved.log 
date > $logfile 2>1& 
find $srcbase -noleaf -atime +30 -print0 | while IFS="" read -r -d "" file ; do 
    if [ -f "$file" ]; then 
    relname="${file#*$srcbase}" 
    destname="$destbase$relname" 
    destdir="$(dirname "$destname")" 
    if [ ! -d "$destdir" ]; then 
     cmd1="mkdir -p \""$destdir"\"" 
     eval "$cmd1" >> $logfile 2>&1 
    fi 
    cmd="mv --backup=t -v \""$file"\" \""$destname"\"" 
    eval "$cmd" >> $logfile 2>&1 
    if [ -e "$destname" ]; then 
     cmd2="touch -a \""$destname"\"" 
     eval "$cmd2" >> $logfile 2>&1 
    fi 
    fi 
done 
date >> $logfile 2>1& 
echo Deleting empty directories from "$srcbase" >> $logfile 2>&1 
find "$srcbase" -type d -empty -delete >> $logfile 2>&1 
+0

你確定$ in的文件沒有被鎖定嗎?通常情況下,名稱中包含$的臨時文件,並且由於已被另一個進程打開,通常它們是不可讀的。 – NibblyPig 2010-10-29 08:46:26

+0

你爲什麼把你的命令放在變量中?例如,直接執行'mv --backup = t -v「$ file」「$ destname」>> $ logfile 2>&1'。這也可以避免你必須做所有那些尷尬的額外引用和轉義。 – 2010-10-29 15:55:27

回答

3

當然,你是。您正在使用eval

BASH FAQ entry #50

+0

+1 [BashFAQ/050](http://mywiki.wooledge.org/BashFAQ/050)是關於避免將命令放入變量(適用於OP的代碼)和[BashFAQ/048](http:// mywiki。 wooledge.org/BashFAQ/048)是關於'eval'的安全問題(也適用)。 – 2010-10-29 15:51:08

3

的問題可能來自於被evaled變量使用的文件名。

,如果您使用的EVAL的設置單引號它可以防止在$解釋有例如爲:

cmd2="touch -a '$destname'" 

創建CMD時$destname仍然取代。

但是:我會強烈反對建設evals從文件名,你在文件系統上找到建議。這是一個巨大的後門。例如:如果某個惡作劇者在源文件系統上創建文件名; rm -rf /,該怎麼辦?

Explanation of the security issues with eval

+0

+1,'eval'是一個危險的工具,需要小心處理。 – DarkDust 2010-10-29 09:04:33

3

你的問題是你的eval使用。我建議不要這樣做,因爲它非常非常非常必要且非常難以使用。我看不出有任何需要它在你的情況

如果這個

if [ -f "$file" ]; then 
    relname="${file#*$srcbase}" 
    destname="$destbase$relname" 
    destdir="$(dirname "$destname")" 
    if [ ! -d "$destdir" ]; then 
     mkdir -p "$destdir" >> $logfile 2>&1 
    fi 
    mv --backup=t -v "$file" "$destname" 
    if [ -e "$destname" ]; then 
     touch -a "$destname" >> $logfile 2>&1 
    fi 
    fi 

取代你的循環的內容應該在文件名中工作一樣好,甚至$。

您是否發現這種情況並非如此?

相關問題