ハードリンクとかシンボリックリンクとか

Windowsは以前まではUnixでよく使われているハードリンクとかシンボリックリンクとかっていうものがなかった。ショートカットとか言うのはあったけど、あれは確かにリンクではあるけどリンク先のファイルがあたかもそこにあるようにつかえるものではなく、メモ帳とかで開いてみるとよくわからないバイナリファイルである。
WindowsにNTが出てきて、NTFSというファイルシステムが開発され、Windows2000になると、ハードリンクとジャンクションが使えるようになった。ジャンクションはフォルダーに対してのシンボリックリンクのようなもの。シンボリックリンクとの違いはよく知らない。
そしてVistaになってようやくシンボリックリンクが使えるようになった。
これを用いることで、違うドライブにあるものまであたかも"ここ"にあるかのように使うことができるようになった。
まぁ聞いただけじゃよくわからないだろうけど、実際にはいろいろ使い道がある。
たとえば、システムドライブのProgram Filesがあまりにも要領を食いすぎていて、ほかのドライブに移せないものか…と思ったらジャンクションかシンボリックリンクを使えばよい。
まずProgram Filesの中身をほかのドライブに移し、それへのリンクまたはジャンクションをシステムドライブに作ればよいのである。
使い道はほかにもたくさんある。こんな便利な機能を使わないわけには行かない。


実はこれをエクスプローラ上で簡単に使うことができるソフトがある。

これを使うと、右クリックでファイルをD&Dすると、「ここに移動」とか「ここにコピー」とか書いてあるメニューに「リンクを作る」が増えるのだ。これは便利だ。


ただ、このソフトはシンボリックリンクを作ることができない。


さっき発見したのだが、このソフトならできるらしい。まだ試してませんが;


あと、リンクを使って仮想的にフォルダをまるごとコピーできたらいいなと前から思っていたので、ちょっと書いてみた。

using System;
using System.Runtime.InteropServices;
using System.IO;

namespace Aont
{
  public enum SymbolicLinkFlag
  {
    File, DIRECTORY
  }

  class Link
  {
    static void Main(string[] args)
    {
      if (args.Length != 2)
        throw new Exception("Invalid Number of Arguments...");

      string link = args[0];
      if (File.Exists(link))
        throw new Exception("There already exists a file!");


      string target = args[1];
      if (Directory.Exists(target))
      {
        DirectoryLink(link,target);
      }
      else if (File.Exists(target))
      {
        CreateLink(link,target);
      }
      else
        throw new Exception("TargetFile does not exist!");

    }

    [DllImport("kernel32.dll", EntryPoint = "CreateHardLink")]
    public static extern bool CreateHardLink(
      string FileName,
      string ExistingFileName,
      object lpSecurityAttributes
      );

    [DllImport("kernel32.dll", EntryPoint = "CreateSymbolicLink")]
    public static extern bool CreateSymbolicLink(
      string SymlinkFileName,
      string TargetFileName,
      SymbolicLinkFlag Flags
      );


    static bool sym = false;
    public static void CreateLink(string LinkFileName, string TargetFileName)
    {
      if (!sym)
      {
        if (CreateHardLink(LinkFileName, TargetFileName, null))
          return;
        else
          sym = true;
      }
      if (!CreateSymbolicLink(LinkFileName, TargetFileName, SymbolicLinkFlag.File))
        throw new Exception(String.Format("CreateLink Failed...\n\nL:{0}\nT:{1}", LinkFileName, TargetFileName));
    }

    public static void DirectoryLink(string link, string target)
    {
      if (Directory.Exists(link))
        throw new Exception("LinkDirectory Already Exists!");
      else
      {
        Directory.CreateDirectory(link);
        
        foreach (string file in Directory.GetFiles(target))
        {
          string linkfile = Path.Combine(link, Path.GetFileName(file));
          string targetfile = file;
          CreateLink(linkfile, targetfile);

        }
        foreach (string file in Directory.GetDirectories(target))
        {
          string linkfile = Path.Combine(link, Path.GetFileName(file));
          string targetfile = file;
          DirectoryLink(linkfile, targetfile);
        }

      }
    }

  }
}

これはフォルダのシンボリックリンクを作るのではなく、フォルダ内のすべてのファイルへのリンクをほかの場所に作るプログラム。
まぁ使い道は自分で考えて。パソコンをよく使う人ならたぶんそのうちそういう要求にぶつかると思います。

link.exe link target

って感じです。