ファイルを別の場所に移動する

Recipe ID: fs-010

ファイルをある場所から別の場所に移動(Move)する方法を紹介します。
Tauri の plugin-fs において、ファイルの移動には「リネーム(rename)」関数を使用します。これは OS のコマンド(mv コマンドなど)と同様の概念です。

前提条件

このレシピを使用するには、@tauri-apps/plugin-fs プラグインが必要です。

1. プラグインのインストール

プロジェクトのルートディレクトリで以下のコマンドを実行してプラグインを追加します。

npm run tauri add fs

2. Permissions (権限) の設定

src-tauri/capabilities/default.json に以下の権限を追加します。

{
  "permissions": [
    ...,
    {
      "identifier": "fs:allow-rename",
      "allow": [{ "path": "$APPLOCALDATA/**" }, { "path": "$DOWNLOAD/**" }]
    }
  ]
}

※ 上記の例では $APPLOCALDATABaseDirectory.AppLocalData)および $DOWNLOADBaseDirectory.Download)配下での移動(リネーム)を許可しています。アクセスするディレクトリに応じて、パス変数を指定してください。スコープが設定されていないディレクトリにはアクセスできません。

1. フロントエンドから作成する (TypeScript)

@tauri-apps/plugin-fsrename 関数を使用します。

同じベースディレクトリ内での移動

BaseDirectory.AppLocalData 内で、ファイルを inbox フォルダから archive フォルダへ移動する例です。

import { rename, BaseDirectory } from '@tauri-apps/plugin-fs';

async function archiveFile() {
  try {
    // inbox/data.txt -> archive/data.txt
    await rename('inbox/data.txt', 'archive/data.txt', {
      oldPathBaseDir: BaseDirectory.AppLocalData,
      newPathBaseDir: BaseDirectory.AppLocalData, // 同じベースディレクトリを指定
    });
    console.log('ファイルをアーカイブへ移動しました');
  } catch (err) {
    console.error('移動エラー:', err);
  }
}

異なるベースディレクトリ間での移動

例えば、ユーザーの「ダウンロード」フォルダにあるファイルを、アプリの「ローカルデータ」フォルダに取り込む(移動する)場合などです。
※ この場合、両方のパスに対する権限(Scope)が必要です。

import { rename, BaseDirectory } from '@tauri-apps/plugin-fs';

async function importDownloadedFile() {
  try {
    // Download/import.json -> AppLocalData/data.json
    await rename('import.json', 'data.json', {
      oldPathBaseDir: BaseDirectory.Download,
      newPathBaseDir: BaseDirectory.AppLocalData,
    });
    console.log('ダウンロードフォルダからファイルをインポート(移動)しました');
  } catch (err) {
    console.error('インポートエラー:', err);
  }
}

2. バックエンドから作成する (Rust)

Rust の std::fs を使用します。

ファイルの移動

use std::fs;

#[tauri::command]
fn move_file(from_path: String, to_path: String) -> Result<(), String> {
    // fs::rename はリネームだけでなく移動も行います
    fs::rename(from_path, to_path).map_err(|e| e.to_string())
}

パス操作を伴う移動

use tauri::Manager;
use std::fs;

#[tauri::command]
fn move_to_app_data(app: tauri::AppHandle, source_path: String) -> Result<(), String> {
    let app_data_dir = app.path().app_data_dir()
        .map_err(|e| e.to_string())?;

    // 移動先のディレクトリが存在することを確認
    if !app_data_dir.exists() {
        fs::create_dir_all(&app_data_dir).map_err(|e| e.to_string())?;
    }

    let file_name = std::path::Path::new(&source_path)
        .file_name()
        .ok_or("Invalid path")?;
        
    let dest_path = app_data_dir.join(file_name);
    
    fs::rename(source_path, dest_path).map_err(|e| e.to_string())
}

補足

  • rename: 名前変更だけでなく、パスを変更することで移動として機能します。
  • クロスデバイスエラー: Rustの std::fs::rename は、異なるマウントポイント(ドライブ)間の移動ではエラーになることがあります。その場合は fs::copy してから fs::remove_file することで代替します。
  • ディレクトリの存在: 移動先の親ディレクトリが事前に存在している必要があります。