pCloudやDropbox、iCloudなどのクラウドストレージを使用していると、同期の競合により「[conflicted]」や「[conflicted 2]」といった文字列が自動的にファイル名に追加されることがあります。

これらのファイルが複数のサブフォルダに散らばっていると、手動での削除は非常に手間がかかります。この記事では、Macのターミナルを使って、サブフォルダを含むすべての[conflicted]ファイルを安全かつ効率的に一括削除する方法を紹介します。

    [conflicted]ファイルとは?

    クラウドストレージサービスでは、複数のデバイスから同じファイルを同時に編集すると、同期の競合が発生します。この際、元のファイルを保護するために、競合したバージョンに[conflicted]という文字列が自動的に付加されます。

    発生する主なケース

    • 複数のデバイスでオフライン編集後に同期
    • 同期完了前に別デバイスで同じファイルを保存
    • ネットワークの不安定による同期エラー
    • バージョン管理システムとの併用時

    事前準備:対象ファイルの確認

    削除を実行する前に、どのファイルが削除対象になるのか確認しましょう。

    ターミナルで対象ファイルを一覧表示

    find "/path/to/directory" -type f -name '*\[conflicted*'
    

    重要ポイント:

    • [conflicted]の角括弧は特殊文字のため、バックスラッシュ \ でエスケープが必要
    • パスにスペースや括弧が含まれる場合は、ダブルクォート " で囲む

    ファイル数をカウント

    find "/path/to/directory" -type f -name '*\[conflicted*' | wc -l
    

    実行例

    find "/Users/pCloud Drive/MyProject" -type f -name '*\[conflicted*'
    

    出力例:

    /Users/pCloud Drive/MyProject/analytics [conflicted].php
    /Users/pCloud Drive/MyProject/demo-pageband [conflicted 2].html
    

    一括削除用シェルスクリプト

    以下のスクリプトを使用することで、安全かつ効率的に[conflicted]ファイルを削除できます。

    スクリプト全文

    #!/bin/bash
    
    # 使用方法:
    # 基本(conflictedファイルのみ):
    #   ./delete_conflicted.sh "/path/to/directory"
    # .DS_StoreとThumbs.dbも削除:
    #   ./delete_conflicted.sh -a "/path/to/directory"
    
    # オプション解析
    DELETE_SYSTEM_FILES=false
    while getopts "a" opt; do
        case $opt in
            a)
                DELETE_SYSTEM_FILES=true
                ;;
            \?)
                echo "無効なオプション: -$OPTARG"
                echo "使用方法: $0 [-a] /path/to/directory"
                echo "  -a: .DS_Store と Thumbs.db も削除する"
                exit 1
                ;;
        esac
    done
    shift $((OPTIND - 1))
    
    if [ -z "$1" ]; then
        echo "使用方法: $0 [-a] /path/to/directory"
        echo "  -a: .DS_Store と Thumbs.db も削除する"
        exit 1
    fi
    
    # 指定されたディレクトリが存在するか確認
    if [ ! -d "$1" ]; then
        echo "エラー: 指定されたディレクトリが存在しません: $1"
        exit 1
    fi
    
    # 削除対象のファイルを表示
    echo "以下のファイルが削除対象です:"
    echo "================================"
    
    # [conflicted]ファイルを検索
    conflicted_count=0
    echo "■ [conflicted] ファイル:"
    find "$1" -type f -name '*\[conflicted*' | while IFS= read -r file; do
        echo "  $file"
    done
    conflicted_count=$(find "$1" -type f -name '*\[conflicted*' | wc -l)
    
    # システムファイルを検索(オプション指定時)
    ds_store_count=0
    thumbs_db_count=0
    if [ "$DELETE_SYSTEM_FILES" = true ]; then
        echo ""
        echo "■ .DS_Store ファイル:"
        find "$1" -type f -name '.DS_Store' | while IFS= read -r file; do
            echo "  $file"
        done
        ds_store_count=$(find "$1" -type f -name '.DS_Store' | wc -l)
        
        echo ""
        echo "■ Thumbs.db ファイル:"
        find "$1" -type f -name 'Thumbs.db' | while IFS= read -r file; do
            echo "  $file"
        done
        thumbs_db_count=$(find "$1" -type f -name 'Thumbs.db' | wc -l)
    fi
    
    # 合計表示
    echo "================================"
    echo "合計:"
    echo "  [conflicted] ファイル: ${conflicted_count} 個"
    if [ "$DELETE_SYSTEM_FILES" = true ]; then
        echo "  .DS_Store: ${ds_store_count} 個"
        echo "  Thumbs.db: ${thumbs_db_count} 個"
        total_count=$((conflicted_count + ds_store_count + thumbs_db_count))
        echo "  総計: ${total_count} 個"
    fi
    echo ""
    
    # 確認を求める
    read -p "これらのファイルを削除しますか? (y/n): " confirm
    if [ "$confirm" != "y" ]; then
        echo "処理を中止しました"
        exit 0
    fi
    
    # 再確認
    read -p "本当に削除しますか?この操作は取り消せません (y/n): " confirm2
    if [ "$confirm2" != "y" ]; then
        echo "処理を中止しました"
        exit 0
    fi
    
    # ファイルの削除を実行
    echo ""
    echo "削除を開始します..."
    echo "================================"
    
    # [conflicted]ファイルを削除
    find "$1" -type f -name '*\[conflicted*' | while IFS= read -r file; do
        rm "$file"
        echo "削除: $file"
    done
    
    # システムファイルを削除(オプション指定時)
    if [ "$DELETE_SYSTEM_FILES" = true ]; then
        find "$1" -type f -name '.DS_Store' | while IFS= read -r file; do
            rm "$file"
            echo "削除: $file"
        done
        
        find "$1" -type f -name 'Thumbs.db' | while IFS= read -r file; do
            rm "$file"
            echo "削除: $file"
        done
    fi
    
    echo "================================"
    echo ""
    echo "処理が完了しました"
    echo "削除されたファイル数:"
    echo "  [conflicted] ファイル: ${conflicted_count} 個"
    if [ "$DELETE_SYSTEM_FILES" = true ]; then
        echo "  .DS_Store: ${ds_store_count} 個"
        echo "  Thumbs.db: ${thumbs_db_count} 個"
        total_count=$((conflicted_count + ds_store_count + thumbs_db_count))
        echo "  総計: ${total_count} 個"
    fi
    

    使用手順

    ステップ1:スクリプトの保存

    1. 上記のスクリプトをテキストエディタにコピー
    2. delete_conflicted.sh という名前で保存
    3. 分かりやすい場所に保存(例:~/Scripts/delete_conflicted.sh

    ステップ2:実行権限の付与

    ターミナルで以下のコマンドを実行します:

    chmod +x ~/Scripts/delete_conflicted.sh
    

    ステップ3:スクリプトの実行

    基本的な使い方(conflictedファイルのみ削除)

    ~/Scripts/delete_conflicted.sh "/Users/pCloud Drive/MyProject"
    

    システムファイルも削除(-aオプション)

    .DS_StoreThumbs.dbも同時に削除したい場合:

    ~/Scripts/delete_conflicted.sh -a "/Users/pCloud Drive/MyProject"
    

    実行例と出力

    ~/Scripts/delete_conflicted.sh "/Users/pCloud Drive/MyProject"
    

    出力例:

    以下のファイルが削除対象です:
    ================================
    ■ [conflicted] ファイル:
      /Users/pCloud Drive/MyProject/analytics [conflicted].php
      /Users/pCloud Drive/MyProject/demo-pageband [conflicted 2].html
    ================================
    合計:
      [conflicted] ファイル: 50 個
    
    これらのファイルを削除しますか? (y/n): y
    本当に削除しますか?この操作は取り消せません (y/n): y
    
    削除を開始します...
    ================================
    削除: /Users/pCloud Drive/MyProject/analytics [conflicted].php
    削除: /Users/pCloud Drive/MyProject/demo-pageband [conflicted 2].html
    ================================
    
    処理が完了しました
    削除されたファイル数:
      [conflicted] ファイル: 50 個
    

    スクリプトの主な機能

    1. 安全性の確保

    • 削除前のファイル一覧表示: 何が削除されるか事前に確認できる
    • 二段階確認: 誤操作を防ぐため、2回の確認プロンプトを実装
    • ディレクトリ存在チェック: 指定パスが存在するか自動確認

    2. 柔軟な削除オプション

    • 基本モード: [conflicted]ファイルのみを削除
    • 拡張モード(-a): システムファイルも同時に削除
      • .DS_Store(Macの隠しファイル)
      • Thumbs.db(Windowsの隠しファイル)

    3. 詳細なレポート

    • ファイル種別ごとの件数表示
    • 削除処理の進捗をリアルタイム表示
    • 処理完了後の集計レポート

    トラブルシューティング

    エラー1:「Permission denied」

    原因: ファイルやディレクトリへのアクセス権限がない

    解決方法:

    # 管理者権限で実行(慎重に)
    sudo ~/Scripts/delete_conflicted.sh "/path/to/directory"
    

    エラー2:「No such file or directory」

    原因: パスの指定が間違っている

    解決方法:

    1. パスをダブルクォートで囲む
    2. lsコマンドでパスを確認
    ls "/Volumes/CT1000P3/pCloud(CT1000P3)"
    

    エラー3:すべてのファイルが対象になる

    原因: 角括弧のエスケープ忘れ

    間違い:

    find "/path" -type f -name '*[conflicted]*'  # NG
    

    正しい:

    find "/path" -type f -name '*\[conflicted*'  # OK
    

    エラー4:スクリプトが実行できない

    原因: 実行権限がない

    解決方法:

    chmod +x ~/Scripts/delete_conflicted.sh
    

    カスタマイズ方法

    異なるパターンのファイルを削除したい場合

    スクリプト内の以下の部分を変更します:

    # 例:「copy」という文字列を含むファイルを削除
    find "$1" -type f -name '*copy*'
    

    ゴミ箱に移動する方式に変更

    完全削除ではなく、ゴミ箱に移動したい場合:

    # rmの代わりにmvを使用
    mv "$file" ~/.Trash/
    

    注意事項とベストプラクティス

    ⚠️ 重要な注意事項

    1. バックアップの取得: 削除は取り消せないため、必ず事前にバックアップを取る
    2. テスト環境で確認: 小さなテストフォルダで動作確認してから本番実行
    3. 同期の停止: クラウドストレージの同期を一時停止してから実行
    4. ファイルの内容確認: 削除前に重要なファイルでないか確認

    推奨手順

    1. クラウドストレージの同期を停止
    2. findコマンドで対象ファイルを確認
    3. 重要なファイルが含まれていないか目視確認
    4. テストディレクトリで動作確認
    5. 本番環境で実行
    6. 同期を再開

    よくある質問(FAQ)

    Q1: 削除したファイルは復元できますか?

    A: rmコマンドによる削除は復元できません。ゴミ箱に移動する方式に変更するか、Time Machineなどのバックアップから復元してください。

    Q2: サブフォルダの深さに制限はありますか?

    A: findコマンドはデフォルトで無制限に再帰検索するため、どれだけ深い階層でも対応可能です。

    Q3: 外付けHDDやネットワークドライブでも使えますか?

    A: はい、マウントされているすべてのドライブで使用可能です。ただし、ネットワークドライブの場合は処理に時間がかかることがあります。

    Q4: 特定のサブフォルダだけを除外できますか?

    A: findコマンドに-pruneオプションを追加することで除外可能です:

    find "$1" -type d -name 'node_modules' -prune -o -type f -name '*\[conflicted*' -print
    

    Q5: Windows環境でも使えますか?

    A: このスクリプトはMac/Linux用です。WindowsではWSL(Windows Subsystem for Linux)やGit Bashを使用すれば同様の処理が可能です。

    まとめ

    この記事では、Macのターミナルを使って[conflicted]ファイルを安全かつ効率的に一括削除する方法を紹介しました。

    ポイントのおさらい

    • findコマンドで角括弧をエスケープ(\[
    • 削除前に必ず対象ファイルを確認
    • 二段階確認で誤削除を防止
    • -aオプションで.DS_Storeも同時削除可能
    • バックアップを取ってから実行

    クラウドストレージを日常的に使用している方にとって、この方法は大量の競合ファイルを効率的に管理するのに役立ちます。特に、開発プロジェクトやクリエイティブワークで多数のファイルを扱う場合、定期的なメンテナンスとして活用できます。

    スクリプトは一度設定すれば繰り返し使用できるため、ぜひ自分の環境に合わせてカスタマイズしてご活用ください。


    関連記事