2013-04-25 108 views
1

我有一個錯誤試圖找到一種方法,用另一個字符串轉換文件路徑轉換爲字符串

sed: Error tryning to read from {directory_path}: It's a directory 

shell腳本

#!/bin/sh 

R2K_SOURCE="source/" 
R2K_PROCESSED="processed/" 
R2K_TEMP_DIR="" 

echo " Procesando archivos desde $R2K_SOURCE " 

for file in $(find $R2K_SOURCE) 
do 
     if [ -d $file ] 
     then 
       R2K_TEMP_DIR=$(sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g' $file) 
       echo "directorio $R2K_TEMP_DIR" 
     else 
#    some code executes 
       : 
     fi 
done 

# find $R2K_PROCCESED -type f -size -200c -delete 

我」替換目錄路徑的字符串米的理解是,這是該行的RROR

R2K_TEMP_DIR=$(sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g' $file) 

,但我不知道怎麼跟sh能治療$文件變量作爲字符串nd不是一個目錄對象。

+1

可能是:'R2K_TEMP_DIR = $(echo $ file | sed's /「$ R2K_SOURCE」/「$ R2K_PROCESSED」/ g')'(儘管您可以指示find來通過'-type獨立查找目錄和文件f' /'-type d' – Wrikken 2013-04-25 19:05:02

+0

@Wrikken它的作品現在寫出來就像一個答案,y會批准你的答案。非常感謝 – Rafael 2013-04-25 19:09:40

+0

Loetar的答案是更正確的,然後我的快速評論;) – Wrikken 2013-04-25 19:12:14

回答

3

首先,不要使用:

for item in $(find ...) 

因爲你可能會重載命令行。此外,for循環無法啓動,直到$(...)中的進程結束。相反:

find ... | while read item 

您還需要注意時髦的文件名。 for循環會在其中有空格的所有文件中咳嗽。只要文件名中只有一個空格而不是雙空格,則find | while就可以工作。更好:

find ... -print0 | while read -d '' -r item 

這將使空文件名之間,並read將打破這些空值。這樣,帶空格,製表符,換行符或其他任何可能導致問題的文件都可以毫無問題地被讀取。

你sed的路線是:

R2K_TEMP_DIR=$(sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g' $file) 

這是什麼嘗試做的是編輯$file這是一個目錄。你想要做的是將目錄名稱本身。因此,你必須名稱呼應成sed爲管道:

R2K_TEMP_DIR=$(echo $file | sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g') 

但是,您可能使用環境變量參數來篩選你的環境變量會更好。

基本上,您有一個名爲source/的目錄,您正在查找的所有文件都位於該目錄下。您只需要換:

source/foo/bar 

processed/foo/bar 

你可以做這樣的事情$ {文件#源/}。 #表示這是一個左側過濾器,它將移除最少量以匹配#之後的glob表達式。檢查bash的聯機幫助頁,並在參數擴展下查看。在它的位置

#!/bin/sh 

R2K_SOURCE="source/" 
R2K_PROCESSED="processed/" 
R2K_TEMP_DIR="" 

echo " Procesando archivos desde $R2K_SOURCE " 

find $R2K_SOURCE -print0 | while read -d '' -r file 
do 
    if [ -d $file ] 
    then 
     R2K_TEMP_DIR="processed/${file#source/}" 
     echo "directorio $R2K_TEMP_DIR" 
    else 
#  some code executes 
     : 
    fi 
done 

R2K_TEMP_DIR="processed/${file#source/}"去除的$file開始的source/,你只是在前面加上processed/

這一點,你可以做這樣的事情。

更好的是,它的效率更高。在您的原始腳本中,$(..)會創建另一個shell進程來運行您的echo,然後將其導出到另一個進程以運行sed。 (假設你使用loentar的解決方案)。您不再有任何子流程在運行。您的目錄名稱的整個修改是內部的。

順便說一句,這也應太:

R2K_TEMP_DIR="$R2K_PROCESSED/${file#$R2K_SOURCE}" 

我只是沒有測試。

+0

使用這種類型的字符串替換'R2K_TEMP_DIR =「$ R2K_PROCESSED/$ {file#$ R2K_SOURCE}」'我怎樣才能從文件路徑基於擴展名前綴(.mib,.MIB ,.我的)等等。我最後一次嘗試它是R2K_NEW_FILE =「$ {$ R2K_TEMP_DIR%$ MIB_EXTENTIONS}」 其中MIB_EXTENTION =「。mib | .MIB | .my」 – Rafael 2013-04-25 22:56:53

+0

這些是g lobs而不是正則表達式。您可以執行'$ {file%。*}',這將刪除所有擴展名。您也可以執行'$ {file%。*(mib | MIB | my)}'來僅刪除特定的表達式。請注意,它是'*(ext1 | ext2 | ext3)',在BASH中,您必須使用'shopt -s extglob'才能使用這些擴展表達式。 – 2013-04-26 04:21:25

8

如果你想ot替換路徑名的一部分,你可以回顯路徑名並將它帶到管道上的sed。 還必須允許將sed命令到雙引號,而不是單一的和變化的分隔符的'命令一樣,通配符:

R2K_TEMP_DIR=$(echo "$file" | sed "s:$R2K_SOURCE:$R2K_PROCESSED:g") 

然後你就可以用裏面的'命令斜線操作。

更新:

更妙的是去除無用的回聲,並使用 「這裏是字符串」,而不是:

R2K_TEMP_DIR=$(sed "s:$R2K_SOURCE:$R2K_PROCESSED:g" <<< "$file") 
+0

更好的答案:D – Rafael 2013-04-25 19:14:02

+0

真的很酷將記住,現在 – Vahid 2013-04-25 19:27:16