2017-03-14 25 views
1

我有一個包含子目錄和文件的目錄(稱爲「源」)。使用bash我需要將在此目錄及其子目錄中找到的所有文件(只有文件,而不是目錄)複製到不同的目錄(稱爲「目標」)。目錄樹不得維護/必須平鋪。只有不包含在文本文件中的文件(稱爲'excluded.txt')必須被複制。如何在壓扁樹結構的同時複製目錄/子目錄中的所有文件(不包括列表中包含的文件)?

源輸入的例子:

/home/source/AAA/file1.xyz 
/home/source/AAA/GGG/file2.xyz 
/home/source/BBB/file3.tuv 
/home/source/BBB/HHH/file4.tuv 

目的地輸出的例子:

/home/destination/file1.xyz 
/home/destination/file2.xyz 
/home/destination/file3.tuv 
/home/destination/file4.tuv 

一旦文件被複制,這四個文件名+(file1.xyz等,)加入到excluded.txt (每個文件名放在一個新行中)。這些文件將被定期從目標目錄中刪除。

如果bash腳本再次執行,並且存在源文件,如果它們的文件名出現在excluded.txt文件中,則不應將它們複製到目標。

由於維護了目錄樹結構,我試圖通過「cp」和「rsync」失敗。我也沒有使用「查找」,因爲在採取複製操作之前,我無法在「excluded.txt」列表中檢查結果。

+0

find/home/source/-type f -exec cp -n {}/home/destination/\; 如果您想避免覆蓋目標文件夾中的現有文件,請使用'cp -n' –

+0

@KuldeepSingh我最初編寫了這段代碼作爲答案,但我忘記考慮到OP有排除文件的文件 – Aserre

+0

可以避免使用cp命令的-n選項來重寫文件。除非排除.txt在其他地方需要 –

回答

0

@Aserre提供的答案有助於找到此解決方案。他的解決方案適用於所有不包含空格的文件。在閱讀eval(評估/執行字符串),string concatenationhow to read entire lines into variables後,我能夠成功編寫並執行以下代碼。

while read -r line 
do 
    name="$line" 
    exclude="$exclude ! -name \"$name\"" 
done < "/mnt/destination/exclude.txt" 
cmd1="find \"/home/source\" -type f " 
cmd2=" -exec cp -n {} \"/home/destination\" \;" 
result=$cmd1$exclude$cmd2 
eval $result 

解釋(信貸@Aserre):

  • while read -r line:經過在exclude.txt每一行。 「-r」標誌會導致反斜槓被認爲是該行的一部分。
  • name="$line":excluded.txt中的整行存儲在名爲「name」的新字符串中。
  • exclude="$exclude ! -name \"$name\"":將! -name "file1" ! -name "file2" ! -name...存儲在一個名爲「exclude」的新字符串中。該字符串是要排除的所有文件的列表,每個文件都以! -name開頭。在每個引號前面都需要反斜槓。
  • cmd1=:將以下2個命令存儲爲名爲「cmd1」的字符串。
  • find /home/source:要搜索的根目錄的路徑。搜索是遞歸的。
  • -type f:僅檢索文件。
  • -exec cp -n {} /home/destination:爲每個找到的項目執行的操作。 {}表示找到的項目。
  • cmd2=:將以前的命令存儲到名爲「cmd2」的字符串中。
  • result=$cmd1$exclude$cmd2:連接所有3個字符串。
  • eval $result:將名爲「result」的字符串作爲命令運行。
1

find應該使用遞歸搜索

find /home/source -type f $(printf "! -name %s" "$(cat exclude.txt)") -exec cp -n {} /home/destination \; 

說明的工具:

  • find /home/source:根目錄的路徑進行搜索。搜索是遞歸的。
  • -type f:僅檢索文件
  • $(printf "! -name %s " $(cat exclude.txt)):會寫! -name file1 ! -name file2 ...,列出所有要排除的文件
  • -exec cp -n {} /home/destination:對於每一個找到的項目執行的動作。 {}代表找到的項目。
+0

完美@Aserre –

+0

@Aserre完美的作品。排除列表可防止文件被重複複製(因爲它們會從目標位置週期性地移除)。非常感謝你! – Bob

+0

@Aserre所以,我只是確定這個代碼只適用於不包含空格的文件名。如果文件名中有空格,例如「file 2.txt」,則在執行代碼時,該文件被重複複製到目標目錄(如果原始副本已從目標目錄中刪除)。 – Bob

相關問題