2017-08-07 83 views
1

我正在嘗試編寫一個shell腳本來備份目錄中的每個文件。 在奧得河得到的文件,我使用用''在bash中替換'''

FILENAMES="$(find -maxdepth 1 -not -path './.*' -type f)" 

返回包含的所有文件名的東西。

如果沒有文件名包含空格,則使用

tar --exclude='archive.tar.bz2' -cvpjf archive.tar.bz2 $FILENAMES 

做這項工作,一切都很好。

但是,如果有一個文件名「壞filename.txt」上述方法不起作用,焦油會抱怨說,它無法找到「文件名.txt」的「壞」。

我試圖通過使用內聯替換描述here來解決這個問題,但是,這並不工作:

TOARCHIVE=${FILENAMES// /'\ '} 

基本上這樣做是更換空間在適當的位置,如果我echo它。但tar似乎沒有看到插入的'\'。如果嘗試用兩個斜槓替換代碼,如'\\''\\ 'tar將看到兩個斜槓並再次發出抱怨。

我看到的類似問題的另一個解決方案是確保所有內容都在引號中,但這對我不起作用,因爲TOARCHIVE包含多個文件的名稱。

+0

您可能需要使用NUL分隔https://www.gnu.org/software/tar/manual/html_node/nul.html - 和通'-print0'來查找。 – ideasman42

回答

0

對於字符替換,我建議你使用sed,像這樣:

sed "s/\ /\\/g" myfile.txt 

這將替換所有空格myfile.txt\

0

我建議不能簡單地用'\ '如果更換' '你想正確引用路徑。

或者:

  • 使用NUL終止(-print0參數找到)
  • 報價使用printf的路徑。

雖然不完全是你問什麼,正確的路徑引用可以使用printf '%q'進行,例如:

FILENAMES="$(
    find -maxdepth 1 -not -path './.*' -type f -print0 | 
    xargs -0 printf '%q\n' 
)" 

這是非常有用的,因爲這意味着在文件路徑等奇怪的字符不會導致以後的問題。

如果一些棘手的人跑touch "foo\ bar.txt"例如:)

0

一種方式來做到這一點是執行tar工具從發現自己:

find -maxdepth 1 -not -path './.*' -type f -exec tar --exclude='archive.tar.bz2' -cvpjf archive.tar.bz2 "{}" + 
+1

這不適用於包含引號的文件名 – ideasman42

+0

@ ideasman42正確。我相信上面的工作。 – Sakis

0
FILENAMES="$(find -maxdepth 1 -not -path './.*' -type f -printf "'"%f"'")" 

打印每個文件名用單引號包圍。

0

不要在常規參數中存儲文件名列表。改爲使用數組參數。你也不需要find;一個簡單的glob將匹配相同的文件。

filenames=(*) # assuming there are no subdirectories in the current directory 

要排除的目錄(和其它非普通文件),使用一個殼循環:

filenames=() 
for f in *; do 
    [[ -f $f ]] && filenames+=("$f") 
done 

一旦陣列被填充,用它作爲

tar --exclude='archive.tar.bz2' -cvpjf archive.tar.bz2 "${filenames[@]}" 

如果您對find有更復雜的調用,我只需將找到的文件名目錄的空終止列表輸入tar不會存入第一(假設GNU tar,反正):

find ... -print0 | tar --null -T - --exclude 'archive.tar.bz2' -cvpjf archive.tar.bz2