Macのフォルダやファイルの並び順をランダムに変えたい

こんな感じでファイルとフォルダの並んだディレクトリ。ここにあるファイルとフォルダの並び順をランダムにしたいんです。

サンプルフォルダスクリーン

せっかくきちんと名前順に並べて整理してくれてるけど、時にはそうせず、ランダムにとっ散らかしたい時もあるもんです。もちろんMacにはそんな変な機能が標準でついてるわけありません。
並び替えに用意されているのは、「名前順」「変更日順」「サイズ」をはじめ、何らかの順番に従って行う物ばかりです。そりゃそうっすよねー。

……だけど、「てきとう」とかあったら素敵だとは思う。

フォルダ/ファイル名に数字を付与して名前で並び替えようか

シンプルに思いつくのは、ファイル名にランダムな数字を付与して、「名前順」で並べてしまう方法です。

こんな感じのファイルとフォルダを……

work
├── folder_0
├── folder_1
├── folder_2
├── folder_3
├── folder_4
├── folder_5
├── file_A.txt
├── file_B.txt
├── file_C.txt
├── file_D.txt
├── file_E.txt
└── file_F.txt

……こんな感じでランダムな順番で並ぶような数字を割り振ってしまいます。これなら数字を付与した後に名前順で並べ替えればそ手軽そうですね。これでいきましょうかー。

work
├── 000-folder_5
├── 010-file_B.txt
├── 020-file_E.txt
├── 030-folder_2
├── 040-folder_1
├── 050-folder_3
├── 060-file_D.txt
├── 070-folder_0
├── 080-file_F.txt
├── 090-folder_4
├── 100-file_A.txt
└── 110-file_C.txt

JXAで書く

こんな事ができるツール、Windowsならファイルリネームの神アプリ「Flexible Renamer」を使えば一発なんだけど、Macではなんだろ?

これくらい、探せばすぐに見つかりそうなんだけど、作っても大した手間にならないだろうし、気が向いたので、今回は作っちゃいます。
とっ散らかすスクリプトが欲しくなる時は、気分もそういう所に入るのかもしれないですね。

ツールや言語も何でも出来そうだけど、利用状況を想像したとき、Finder上で選択したアイテムに適用させるイメージがあったので、今回はMacのスクリプトエディタ.appでJavaScript(JXA)で書いちゃいます。

必要な機能

  • Finder内で選択したフォルダ/ファイルにランダムな数字を割り振る

せっかくなので欲しい機能

  • 適当過ぎる数字を割り振るのも雑なので、例えば12個のアイテムを対象とした場合、10〜120まで、10刻みの数字を割り振る様にする。
  • 「000-folder5」「000folder5」「000folder_5」数字と元のファイル名に任意の接頭辞を設定しやすい構造に。
  • 複数回適用すると「020-070-000-folder_5」と、どんどん数字が増えるのはかっこ悪いので対策する。
  • 数字を付与する前に元に戻す機能も欲しい。
  • 「.DS_Store」など、先頭にドットのつくフォルダ/ファイルは選択してても対象にする必要は無さそう。

……この辺を欲張り過ぎるとキリがないので、程々に抑えなきゃですね(笑)

できた

ランダムな数字を割り振る

思ってたより手間がかかったけど、欲しい機能は全部そろったので満足です。 下記2つのコードをスクリプトエディタ.appに貼り付けて、上のサンプルの様な感じで使えば動くはずです。

選択したフォルダとファイルにランダムな数字を付与する.scpt

var finder = Application("Finder");

// 最前面のウィンドウで選択されているフォルダ/ファイルを取得
var selection = finder.selection();

// 付与する数字と元の名前の接頭辞の正規表現
var prefix = "\-";

// 付与する数字と接頭辞の正規表現
var pattern = new RegExp("^\\d+" + prefix);

// フィッシャー・イェーツのシャッフルを使い、
// 選択したフォルダ/ファイルオブジェクト配列をシャッフル
/*
 * https://ja.wikipedia.org/wiki/フィッシャー_-_イェーツのシャッフル
 * https://bost.ocks.org/mike/shuffle/
 */
function shuffle(array) {
  var m = array.length, t, i;

  // While there remain elements to shuffle…
  while (m) {

    // Pick a remaining element…
    i = Math.floor(Math.random() * m--);

    // And swap it with the current element.
    t = array[m];
    array[m] = array[i];
    array[i] = t;
  }

  return array;
}

ss = shuffle(selection);


// 番号を付与
for (var i = 0; i < ss.length; i += 1) {
  // 「.DS_Store」など、ドットで始まる名前のフォルダ/ファイルは除外する
  if ( Boolean( ss[i].name().match(/^\./) ) ) {
    continue;
  }
  var newName = ss[i].name();

  // 既に数字が振られている場合は、それを削除して付け直す
  var match = ss[i].name().match(pattern);  
  if (match) {
    newName = newName.replace(pattern, "");
  }

  // 付与する数字をゼロ埋めし、手動で順番調整できる余地を少し残すために
  // 末尾に0を追加
  sLength = String(ss.length).length;
  var num = (Array(sLength).join("0") + i).slice(-sLength) + "0";

  newName = num + prefix + newName;
  ss[i].name = newName;

}

ランダム数字を付けられたフォルダとファイルを元に戻す.scpt

var finder = Application("Finder");

// 最前面のウィンドウで選択されているフォルダ/ファイルを取得
var selection = finder.selection();

// 付与する数字と元の名前の接頭辞の正規表現
var prefix = "\-";

// 付与する数字と接頭辞の正規表現
var pattern = new RegExp("^\\d+" + prefix);

// 選択したアイテムを走査してリネーム
selection.forEach(function(e) {
  e.name = e.name().replace(pattern, "")
});

やったね!
これで思う存分とっ散らかす事ができますね。