Introduction
This article presents some small toy console applications that emulate the Unix command like behavior on Windows.
Background
A while ago, my cousin (age: 10 years approx) came to me and asked me to install Unix on his computer. I asked him why he needed that, as a 10 year boy has little to do with Unix. He then told me that he needed to practice an assignment that involves running some Unix commands. He showed me a list of commands that he needed to run.
- ls
- cd
- pwd
- mkdir
- rmdir
- cp
- mv
- rm
- cat
- more
- grep
- whoami
- ps
I was not ready to put Linux on his machine just to run these basic commands. I could give him something like "cygwin" or "coreutils" and he would be fine. Then I thought, Windows already has these commands but with some other names so why not just create a wrapper around those and/or write simple 2-3 line programs to emulate these commands. So I spent half an hour in front of the computer and created these basic commands. Although they are not a very good replacement for the real Unix environment, I guess it was good enough for that 10 year old boy's assignment. So here I am sharing these small utilities.
Using the Code
After I was done with this small exercise, the status of commands was:
ls - Implemented simple optionless
cd - Not Implemented as it exist in windows too
pwd - Implemented
mkdir - Not Implemented as it exist in windows too
rmdir - Not Implemented as it exist in windows too
cp - Implemented
mv - Implemented
rm - Implemented
cat - Implemented
more - Implemented (windows has its own version but ours will work along with that)
grep - Implemented
whoami - Implemented
ps - Implemented (optionless)
So let us look at the small code snippets written for these tiny programs.
ls
static void Main(string[] args)
{
if (args.Length == 0)
{
DirectoryInfo dir = new DirectoryInfo(Directory.GetCurrentDirectory());
foreach (DirectoryInfo d in dir.GetDirectories())
{
Console.WriteLine("{0, -30}\t directory", d.Name);
}
foreach (FileInfo f in dir.GetFiles())
{
Console.WriteLine("{0, -30}\t File", f.Name);
}
}
}
pwd
static void Main(string[] args)
{
Console.WriteLine(Directory.GetCurrentDirectory());
}
cp
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("The syntax of the command is incorrect.");
}
else
{
if (File.Exists(args[0]) == false)
{
Console.WriteLine("Source file not found");
}
else if (Directory.Exists(args[1]) == false)
{
Console.WriteLine("Target Directory not found");
}
else
{
File.Copy(args[0], args[1] + "\\" + args[0]);
}
}
}
mv
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("The syntax of the command is incorrect.");
}
else
{
if (File.Exists(args[0]) == false)
{
Console.WriteLine("Source file not found");
}
else if (Directory.Exists(args[1]) == false)
{
Console.WriteLine("Target Directory not found");
}
else
{
File.Move(args[0], args[1] + "\\" + args[0]);
}
}
}
rm
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.WriteLine("The syntax of the command is incorrect.");
}
else
{
if (File.Exists(args[0]) == false)
{
Console.WriteLine("File not found");
}
else
{
Console.WriteLine("Are you sure you want to delete {0} (y/n)", args[0]);
ConsoleKeyInfo key = Console.ReadKey();
if (key.Key == ConsoleKey.Y)
{
File.Delete(args[0]);
Console.WriteLine("\nFile Deleted: {0}", args[0]);
}
}
}
}
cat
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.WriteLine("The syntax of the command is incorrect.");
}
else
{
if (File.Exists(args[0]) == false)
{
Console.WriteLine("File not found");
}
else
{
string contents = File.ReadAllText(args[0]);
Console.Write(contents);
}
}
}
more
class Program
{
static void Main(string[] args)
{
Process.Start("cat " + args[0] + " | more");
}
}
grep
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("The syntax of the command is incorrect.");
}
else
{
if (File.Exists(args[1]) == false)
{
Console.WriteLine("File not found");
}
else
{
string[] lines = File.ReadAllLines(args[1]);
foreach (string line in lines)
{
if(line.Contains(args[0]))
{
Console.WriteLine(line);
}
}
}
}
}
whoami
static void Main(string[] args)
{
Console.WriteLine(Environment.UserName);
}
ps
static void Main(string[] args)
{
Process[] mYProcs = Process.GetProcesses();
Console.WriteLine("-----------------------------------------------------");
Console.WriteLine("{0, -8} {1, -30} {2, -10}", "PID", "Process Name", "Status");
Console.WriteLine("-----------------------------------------------------");
foreach (Process p in mYProcs)
{
try
{
Console.WriteLine("{0, -8} {1, -30} {2, -10}", p.Id,
p.ProcessName, p.Responding ? "Running" : "IDLE");
}
catch (Exception)
{
continue;
}
}
}
NOTE: Check out the source code for implementation.
IMPORTANT: The folder that contains these commands should be added in the PATH
environment variable.
Points of Interest
At the end of this exercise, I thought about what I did and the only thing I could think of is that perhaps I should have used C++ to implement these commands. That way, I could relieve the users from the burden of having the .NET runtime on their system. But since it solved my purpose, I didn't spend much time on it later. Perhaps, when I get time, I would like to do some more things like:
- Having all the Unix commands implemented and not just these few
- Write similar programs in C++
- Perhaps write the wrappers for Unix like system calls to work on Windows
I will get to these activities once I get some free time from my "real" job.
History
- Version 1: Basic Unix commands implementation