~/Documents
フォルダを ~/Library/backUP/Documents
にコピーした前提であれば。
ファイルやフォルダのコピー・移動は、先のパスに既にアイテムが存在すると失敗します。
~/Library/backUP/Documents
フォルダを ~/Documents
へ戻そうとしても既に ~/Documents
が存在しているので File exists
になったと考えられます。
FileManager
には replaceItemAt(_:withItemAt:backupItemName:options:)
メソッド(公式リファレンス )もあります。
コピーではなく置き換えなので、置き換え先(~/Documents
)の既存内容は全て無くなり、置き換えが成功した場合は置き換え元(~/Library/backUP/Documents
)が削除されますが、ニーズに近い機能ではないかと。
swift
1 func CopyTest ( ) {
2 let fileManager = FileManager . default
3 let libraryUrl = fileManager . urls ( for : . libraryDirectory , in : . userDomainMask ) [ 0 ]
4 let backupUrl = libraryUrl . appendingPathComponent ( "backUP/Documents" , isDirectory : true )
5
6 // バックアップファイルがなければ実行しない
7 var isDirectory = ObjCBool ( false )
8 if ( ! fileManager . fileExists ( atPath : backupUrl . path , isDirectory : & isDirectory ) ||
9 ! isDirectory . boolValue ) {
10 print ( "バックアップがないか、フォルダではありません。" )
11 return
12 }
13
14 // バックアップと既存のフォルダを置き換える
15 let documentUrl = fileManager . urls ( for : . documentDirectory , in : . userDomainMask ) [ 0 ]
16 let temporaryName = "Replaced_Documents"
17 do {
18 _ = try fileManager . replaceItemAt ( documentUrl , withItemAt : backupUrl , backupItemName : temporaryName , options : . usingNewMetadataOnly )
19 print ( "バックアップに置き換えました。" )
20
21 } catch {
22 print ( "置き換えに失敗しました。" , error . localizedDescription )
23
24 // 失敗したにも関わらず一時退避したファイルが元に戻されていない場合
25 if ( ! fileManager . fileExists ( atPath : documentUrl . path ) ) {
26 let userInfo = ( error as NSError ) . userInfo
27 do {
28 if let temporaryUrl = userInfo [ "NSFileOriginalItemLocationKey" ] as ? URL {
29 // エラーに格納されたURLから元の場所に移動する
30 try fileManager . moveItem ( at : temporaryUrl , to : documentUrl )
31 print ( "置き換え前のフォルダを復旧しました。" )
32 }
33 } catch {
34 print ( "作業の失敗からの復旧に失敗しました。" , error . localizedDescription )
35 }
36 }
37 }
38 }
フォルダそのものではなく、フォルダの中身 を別の場所に移したい場合、一括して行ってくれる機能はない ので、フォルダの中身のリストを取得し、ひとつひとつコピー先のパスを作成して実行することになります。
次の例では ~/Library/backUP/Documents
の中身を取得してひとつひとつ ~/Documents
へコピーしていますが、~/Documents
に元々あるアイテムは削除されません。同名のファイルがある場合どうするかも考える必要があります。
swift
1 func CopyTest ( ) {
2 let fileManager = FileManager . default
3 let libraryUrl = fileManager . urls ( for : . libraryDirectory , in : . userDomainMask ) [ 0 ]
4 let backupUrl = libraryUrl . appendingPathComponent ( "backUP/Documents" , isDirectory : true )
5 let documentUrl = fileManager . urls ( for : . documentDirectory , in : . userDomainMask ) [ 0 ]
6
7 // バックアップフォルダの中身を取得する
8 if let itemUrls = try ? fileManager . contentsOfDirectory (
9 at : backupUrl ,
10 includingPropertiesForKeys : nil ,
11 options : [ . skipsSubdirectoryDescendants , . skipsHiddenFiles ]
12 ) {
13 // アイテムのURLをひとつひとつ取得して`~/Documents`の中へコピーする
14 for itemUrl in itemUrls {
15 let toUrl = documentUrl . appendingPathComponent ( itemUrl . lastPathComponent )
16 if ( fileManager . fileExists ( atPath : toUrl . path ) ) {
17 // 同名のファイルが存在する場合の処理
18 // ...
19 } else {
20 do {
21 try fileManager . copyItem ( at : itemUrl , to : toUrl )
22 } catch {
23 print ( "コピーに失敗" , error . localizedDescription )
24 }
25 }
26 }
27 }
28 }