2013-11-05 74 views
1

我發現有幾個類似的問題有解決方案,只是它們不涉及變量。使用替換和變量重命名文件和目錄

我在文件和目錄的樹中有特定的模式 - 模式是單詞模板。我想要一個腳本文件來重命名所有的文件和目錄,用變量$ {newName}

中包含的一些其他名稱替換單詞TEMPLATE如果我知道$ {newName}的值是「弗雷德住在這裏」,然後在命令

find . -name '*TEMPLATE*' -exec bash -c 'mv "$0" "${0/TEMPLATE/Fred lives here}"' {} \; 

將做的工作

但是,如果我的腳本是:

newName="Fred lives here" 
find . -name '*TEMPLATE*' -exec bash -c 'mv "$0" "${0/TEMPLATE/${newName}}"' {} \; 

然後Word模板由n代替ULL而不是「弗雷德住在這裏」

我需要的「」大約$ 0,因爲有在路徑名稱空間,所以我不能做這樣的事情:

find . -name '*TEMPLATE*' -exec bash -c 'mv "$0" "${0/TEMPLATE/"${newName}"}"' {} \; 

誰能幫助我得到這個腳本工作,使得包含Word模板的所有文件和目錄都模板代替任何的${newName}

例如,如果newName="A different name"和我有

/foo/bar/some TEMPLATE directory/with files目錄,然後日Ë目錄將被重新命名爲

/foo/bar/some A different name directory/with files

和一個名爲some TEMPLATE file文件將被重新命名爲

some A different name file

+0

你不想'$ 0'這些表達式。 '$ 0'的值是正在運行的程序,'bash -c'腳本的值是'bash''。 你正在使用哪種類型的系統?我會尋找'rename'命令並利用它。 –

+0

@Mark Reed。我不認爲_rename_命令可以做目錄。至少我不能讓它工作 - 我確實嘗試過。儘管* 0 *不是正確的,它的工作原理,所以我會堅持下去。 – rednectar

回答

1

你有兩個選擇。

1)最簡單的解決方案是export newName。如果您不導出變量,那麼它不可用於子殼中,並且bash -c是一個子殼。這就是爲什麼你將TEMPLATE換成沒有。

2)或者,您可以嘗試構建一個正確引用的命令行,其中包含替換$newName。如果你知道$newName是相當乖巧的(沒有雙引號或美元符號,例如),那麼它很簡單:

find . -name '*TEMPLATE*' \ 
     -exec bash -c 'mv "$0" "${0/TEMPLATE/'"${newName}"'}"' {} \; 

(注:bash的報價是充滿玄機以下已編輯幾個次,但我認爲現在是正確的。)

但是,既然你不能指望這一點,可能需要通過將文件名和替換替換爲命令行參數來構建命令行。但在我們這樣做之前,我們來修復$0。你不應該使用$0作爲參數。正確的語法是:

bash -c '...$1...$1...' bash "argument" 

注意額外bash(很多人喜歡使用_);它在那裏爲子流程提供了一個合理的名稱。

所以考慮到這一點:

find . -name '*TEMPLATE*' \ 
     -exec bash -c 'mv "$1" "${1/TEMPLATE/$2}"' bash {} "$newName" \; 
+0

出口建議很好,但沒有告訴我該怎麼做。 (感謝cforbish,儘管)。我嘗試了兩種選擇: 第一個導致嵌入引號的新名稱 - 如 /foo/bar /一些「Fred住在這裏」目錄/帶有文件 第二個選項在名稱中嵌入反斜槓字符\所以我結束了這些名字如: /foo/bar /一些Fred \ lives \ Here目錄/帶有文件 – rednectar

+0

@rednectar:yup,對不起。在兩個命令行中都有額外的引號;我刪除了它們。 ('export newName' * *是*如何導出newName;您可以在之前,在cforbish的示例中 - 或者在您設置其值之後執行此操作。一旦將變量標記爲導出,它將保持該方式即使你重新分配了變量的值,對不起,假設這是顯而易見的。) – rici

+0

修正後的第一個選項現在可用(使用'$ 0'的那個)。 'printf'版本不會重命名任何東西。 – rednectar

2

您的出行不必使用引號與IFS=$'\n',自bash -c是一個子shell所需的任何變量的export。這工作:

#!/bin/bash 
IFS=$'\n' 
export newName="Fred lives here" 
find . -name '*TEMPLATE*' -exec bash -c 'mv "$0" "${0/TEMPLATE/${newName}}"' {} \; 

如果你不介意的兩行,想一個腳本,更易於閱讀(無需導出):

#!/bin/bash 
IFS=$'\n' 
newName="Fred lives here" 
for file in $(find . -name '*TEMPLATE*'); do 
    mv ${file} ${file/TEMPLATE/${newName}} 
done 
+0

導出選項是缺失的鏈接 - 謝謝你,那個但是for循環沒有起作用 - 變量文件沒有選擇整個路徑/文件名,只有路徑中的第一個空格。 [能夠有足夠業力的人投票回答這個問題嗎?] – rednectar

+0

Did出口'find'方法d爲你工作?如果你修改上一個腳本中的'mv'命令爲'echo',它說什麼? – cforbish

+0

如果在'mv'前面加上'echo',我會得到如下輸出: 'mv ./foo/bar/some TEMPLATE directory/with files/foo/bar /一些Fred住在這裏directory/with files' - I猜測我需要引用它來擺脫空間,或者通過額外的過程來擺脫空間。無論如何 - 'export newName =「Fred住在這裏」'像一個魅力一樣工作,所以問題解決了(儘管別人說我不應該使用$ 0)。 – rednectar