A Quick guide to Cygwin commands for the deprived of the DOS world

Things have been a bit hectic in my world lately. In addition to all the festive seasonal joy ( shopping, family, in-laws, out-laws etc) I’m in the process of changing jobs.

It is the way of such things that sometimes, you just can’t quite squeeze everything in.

The one thing I didn’t get time to finish before leaving was this DOS to BASH guide ( despite several evenings spent hacking away on Windows). So, for the CIG guys…well, it’s traditional – all kids know that there’s got to be at least one Christmas present that you can bash. Sorry.

After years of struggling with the limitations of the Command Window ( henceforth referred to as DOS for the benefit of old-timers like me), you’ve finally gotten around to installing Cygwin.

Cygwin allows you to access DOS/Windows command ( e.g. notepad). If you’re having trouble with permissions on adding stuff to your path variable, there’s a workaround here.

What follows here is a quick run-through of the commands available in the default cygwin configuration, where they differ from their DOS counterparts, and some of the extra goodies that Cygwin offers.

Let’s start with …

Basic Commands

DOS UNIX
help man
date date
dir dir
cp cp
cd cd ( and pwd)
ren mv
type cat
more less

First up is a command you’ll probably use quite a bit – man ( short for manual).
It’s essentially the same as the DOS help command, the syntax is man command :

$ man date

This will display the man page for the date command :

DATE(1)                          User Commands                         DATE(1)

NAME
       date - print or set the system date and time

SYNOPSIS
       date [OPTION]... [+FORMAT]
       date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]

DESCRIPTION
       Display the current time in the given FORMAT, or set the system date.

       -d, --date=STRING
              display time described by STRING, not `now'

       -f, --file=DATEFILE
              like --date once for each line of DATEFILE

       -r, --reference=FILE
              display the last modification time of FILE

       -R, --rfc-2822
              output  date  and time in RFC 2822 format.  Example: Mon, 07 Aug
              2006 12:34:56 -0600
:

The output is a screen page at a time. Press Enter to scroll to the next line. Type q to quit.

The date command itself differs from the DOS date command in that it does not give you the option to change the system date :

$ date
Fri Oct 29 09:38:52 GMTDT 2010

The bash dir command is actually synonymous with the more traditional ls command. It therefore uses the same switches as ls and not those in the DOS dir command.
On it’s own, dir will simply list the file names in a directory :

$ dir
hello.sh  wisdom.sh

To get a long listing :

$ dir -l
total 1
-rwxrwxrwx 1 Mike None  0 2010-08-30 13:29 hello.sh
-rwxrwxrwx 1 Mike None 56 2010-08-30 13:32 wisdom.sh

To list files by timestamp ( newest first )

$ dir -t
wisdom.sh  hello.sh

And to list all files in the directory ( including hidden files) :

$ dir -a
.  ..  .bash_history  .bash_profile  .bashrc  .inputrc  hello.sh  wisdom.sh

You can combine these switches in a single call to get the output you require :

$ dir -tal
total 21
-rw-------  1 Mike None 3678 2010-10-28 18:12 .bash_history
-rwxrwxrwx  1 Mike None   56 2010-08-30 13:32 wisdom.sh
drwxr-xr-x+ 1 Mike None 4096 2010-08-30 13:29 .
-rwxrwxrwx  1 Mike None    0 2010-08-30 13:29 hello.sh
drwxrwxrwt+ 1 Mike root    0 2010-08-25 18:03 ..
-rwxr-xr-x  1 Mike None 1150 2010-08-25 17:55 .bash_profile
-rwxr-xr-x  1 Mike None 1461 2010-08-25 17:55 .inputrc
-rwxr-xr-x  1 Mike None 3754 2010-08-25 17:55 .bashrc

As with DOS, you can use dir to list specific files :

$ dir -l wis*
-rwxrwxrwx 1 Mike None 56 2010-08-30 13:32 wisdom.sh

A minor difference between the DOS and Unix cd commands is that, wheras cd on it’s own in DOS will display the current directory, in Unix it will take you to the directory defined in the $HOME environment variable.
In Unix, if you want to know which directory you’re in, you need to use pwd ( print working directory) :

$ pwd
/home/Mike

Incidentally, if you want to see what $HOME is set to, you can simply issue the command :

$ echo $HOME
/home/Mike

To check all environment variables, paginating the output ( yes, in Cygwin, less is more):

env | less

Command line Recall

The Unix equivalent to Doskey is the command :

set -o vi

This will allow access to command line history and editing…using vi commands.
Esc K is to get the previous command
Esc J to get the next command
Esc I to begin inserting text into a command line

That’s the routine stuff out of the way, now onto some goodies…

Searching and Comparison Tools

If you want to find a file without having to look at that annoying puppy, there’s the find command.

$ find . -name wisdom.sh
./wisdom.sh

You simply specify the directory in which to begin searching ( in this case, the current directory) and then the name of the file after the -name switch and find will search the starting directory and all sub-directories recursively before reporting back any matches.

Searching for text inside a file requires the use of the grep command. To demonstrate, here’s a rather silly text file called silly.txt :

This is a silly text file 
which contains lots of lines with the
word "silly" in them
Silly
silly
SILLY
really sillY
very silly
really very silly
utterly sensible
er, nope, still silly

To print out all the lines with the word silly….

$ grep 'silly' silly.txt
This is a silly text file
word "silly" in them
silly
very silly
really very silly
er, nope, still silly

Hang on, we’ve missed all the lines where the word silly is not all in lowercase. Let’s try again using the -i switch ( ignore case) :

$ grep -i 'silly' silly.txt
This is a silly text file
word "silly" in them
Silly
silly
SILLY
really sillY
very silly
really very silly
er, nope, still silly

If we want to get a count of the number of lines in which our search string is present, we can pipe the output through wc ( word count) and use the -l switch to return the line count. Now, on a scale of 1 to 10, just how silly is this file ?

$ grep -i 'silly' silly.txt |wc -l
9

You can use head and tail to see the first ( or last) several lines of a file :

$ head -3 silly.txt
This is a silly text file
which contains lots of lines with the
word "silly" in them

$ tail -2 silly.txt
utterly sensible
er, nope, still silly

You can order output lines of a command using sort. Consider a file listing like this :

$ ls -tal
total 22
-rwxrwxrwx  1 Mike None   23 2010-12-23 16:36 hello.sh
-rw-------  1 Mike None 3812 2010-10-29 10:37 .bash_history
-rwxrwxrwx  1 Mike None   56 2010-08-30 13:32 wisdom.sh
drwxr-xr-x+ 1 Mike None 4096 2010-08-30 13:29 .
drwxrwxrwt+ 1 Mike root    0 2010-08-25 18:03 ..
-rwxr-xr-x  1 Mike None 1150 2010-08-25 17:55 .bash_profile
-rwxr-xr-x  1 Mike None 1461 2010-08-25 17:55 .inputrc
-rwxr-xr-x  1 Mike None 3754 2010-08-25 17:55 .bashrc

If we now pipe through sort, the output is re-arranged in alphabetical order :

$ ls -tal |sort
-rw-------  1 Mike None 3812 2010-10-29 10:37 .bash_history
-rwxr-xr-x  1 Mike None 1150 2010-08-25 17:55 .bash_profile
-rwxr-xr-x  1 Mike None 1461 2010-08-25 17:55 .inputrc
-rwxr-xr-x  1 Mike None 3754 2010-08-25 17:55 .bashrc
-rwxrwxrwx  1 Mike None   23 2010-12-23 16:36 hello.sh
-rwxrwxrwx  1 Mike None   56 2010-08-30 13:32 wisdom.sh
drwxr-xr-x+ 1 Mike None 4096 2010-08-30 13:29 .
drwxrwxrwt+ 1 Mike root    0 2010-08-25 18:03 ..

If you want to compare two files, you can use the diff command. Whilst we’re at it, to manufacture an example we can use sed – the stream editor. This utility, together with awk delivers a huge boost in command-line and batch scripting power over plain old DOS.
To start with, let’s play around with silly.txt to create a file to compare it against :

$ sed s/silly/sensible/ silly.txt >sensible.txt

All we’ve done here is used sed to substitute every occurrence of the string “silly” with the string “sensible” and redirected the output to a file called sensible.txt.
Now to check the contents of the new file…

$ cat sensible.txt
This is a sensible text file
which contains lots of lines with the
word "sensible" in them
Silly
sensible
SILLY
really sillY
very sensible
really very sensible
utterly sensible
er, nope, still sensible

Now let’s use diff to check the differences between the two files :

$ diff silly.txt sensible.txt
1,11c1,11
< This is a silly text file
< which contains lots of lines with the
< word "silly" in them
< Silly
< silly
< SILLY
< really sillY
< very silly
< really very silly
< utterly sensible
< er, nope, still silly
\ No newline at end of file
---
> This is a sensible text file
> which contains lots of lines with the
> word "sensible" in them
> Silly
> sensible
> SILLY
> really sillY
> very sensible
> really very sensible
> utterly sensible
> er, nope, still sensible
\ No newline at end of file

You can do some comparison on binary files as well, using cksum, which reports back a checksum of the binary file. I’ve got a file called file1.odt – an Open Office Document :

$ cksum file1.odt
4224136109 7698 file1.odt

The cksum command has given us a checksum, the size of the file in bytes and the file name.
If you want to know if two binary files are identical, looking to see if they have the same checksum is usually a good place to start.

Other stuff to play around with

There’s lots of stuff I’m not going to cover here but is probably worth a mention ( gzip – the compression utility for one).
There are lots of sites that explain this stuff rather better and in more depth than I can do here and I’ve listed some of them at the end of this post.

A couple of useful little gems before I wrap up though :

The csplit utility allows you to split a large file into several smaller ones either by number of lines or by splitting when a specific string is found.
For example, I’ve created a file listing the tables in my database ( SELECT table_name FROM all_tables). The file is called tables.lis

$ cat tables.lis |wc -l
1120

So, it’s got 1120 lines in it. If I want to split this into files containing no more than 100 lines, I can do this :

$ csplit -k tables.lis 100 {*}
7997
8200
8200
8200
8200
8200
8200
8200
8200
8200
8200
csplit: `100': line number out of range on repetition 11
1435

The -k switch means write the new files even if there is an error. 100 is the number of lines per file.
The {*} bit is the regular expression to match on. In this case anything at all as I want files of 100 lines each ( plus one of 20) irrespective of what’s in there.
We need the -k switch because csplit objects to those last 20 lines. Using this, we do ensure that the smaller files are created ( all prefixed xx by default) :

$ ls -l xx*
-rw-r--r-- 1 Mike None 7997 2010-12-23 18:57 xx00
-rw-r--r-- 1 Mike None 8200 2010-12-23 18:57 xx01
-rw-r--r-- 1 Mike None 8200 2010-12-23 18:57 xx02
-rw-r--r-- 1 Mike None 8200 2010-12-23 18:57 xx03
-rw-r--r-- 1 Mike None 8200 2010-12-23 18:57 xx04
-rw-r--r-- 1 Mike None 8200 2010-12-23 18:57 xx05
-rw-r--r-- 1 Mike None 8200 2010-12-23 18:57 xx06
-rw-r--r-- 1 Mike None 8200 2010-12-23 18:57 xx07
-rw-r--r-- 1 Mike None 8200 2010-12-23 18:57 xx08
-rw-r--r-- 1 Mike None 8200 2010-12-23 18:57 xx09
-rw-r--r-- 1 Mike None 8200 2010-12-23 18:57 xx10
-rw-r--r-- 1 Mike None 1435 2010-12-23 18:57 xx11

One final goody before I get on to the question of which command prompt you fancy using – putclip let’s you send the output of a command to the clipboard….

$ echo $HOME |putclip

$

If I now do the Window Paste thing here I get :

/home/Mike

Running Cygwin from the DOS Prompt

All the examples I’ve used in this post are written using the default Cygwin command prompt. However, there is more than one way to do this.

If you include the cygwin/bin directory in you DOS path, you can exexute the cygwin command in-line at the DOS prompt.

C:\Users\Mike>set PATH=%PATH%;c:\cygwin\bin

C:\Users\Mike>cd c:\cygwin\home\Mike

c:\cygwin\home\Mike>ls
file1.odt  sensible.txt  tab_head.lis  tables.lis  xx00  xx02  xx04  xx06  xx08  xx10
hello.sh   silly.txt     tab_tail.lis  wisdom.sh   xx01  xx03  xx05  xx07  xx09  xx11

c:\cygwin\home\Mike>grep -i 'silly' silly.txt |wc -l
9

c:\cygwin\home\Mike>

There are a couple of differences to running at the $ prompt.
First of all, cygwin uses aliases to reference certain commands. This is a Unix feature that allows you to type a given command which actually executes a different command.
If we go back to the cygwin shell for a moment, we can run a command to tell us what aliases are being used :

$ ls -l |grep '>' |awk '{print $8, $10}'
awk gawk.exe
bzcmp bzdiff
bzegrep bzgrep
bzfgrep bzgrep
bzless bzmore
lzcat xz.exe
lzcmp xzdiff
lzdiff xzdiff
lzegrep xzgrep
lzfgrep xzgrep
lzgrep xzgrep
lzless xzless
lzma xz.exe
lzmore xzmore
manpath man.exe
unlzma xz.exe
unxz xz.exe
xzcat xz.exe
xzcmp xzdiff
xzegrep xzgrep
xzfgrep xzgrep

The first column is the alias and the second is the actual command being run.
So, to use a recursive example, if we wanted to run the awk command at the DOS prompt, we would need to use gawk.
Incidentally, the above command won’t work at all in DOS as grep does not seem to return any results when searching for the ‘>’. I have no idea why this is at the moment. The grep command seems to work as normal in other circumstances.

The other main differences are that dos commands seem to take precedence. For example, dir works as expected whilst dir -l :

c:\cygwin\bin>dir -l
 Volume in drive C has no label.
 Volume Serial Number is 43AD-644B

 Directory of c:\cygwin\bin

File Not Found

c:\cygwin\bin>

Running shell scripts requires the use of sh rather than the standard ./ :

c:\cygwin\home\Mike>sh wisdom.sh
Rage against the dying of the light!

c:\cygwin\home\Mike>

Running Cygwin in a terminal

I recently had a comment from Matt on my original cygwin post. He recommended using a patched version of Putty called Puttycyg. So, if like Matt you crave an escape from the DOS prompt but find that Cygwin alone just doesn’t quite do it for you….

  1. Go to http://code.google.com/p/puttycyg/
  2. Click on the download link and download the file ( in my case, puttycyg-20101029.zip)
  3. Once unzipped run putty,exe

Choose the connection type Cygterm and the field for the host name changes to Command Line.
Just enter a “-” and hit open.

There you go, Cygwin in a putty terminal. It works in more or less the same way, but you get all the advantages of Putty such as double-click cut and paste etc.

Some Shell Scripting Links

There’s a pretty good basic introduction to shell scripting here.

An introduction to sed can be found here
and an awk primer here.

Say goodbye to the one miserable looping construct, banish those gotos and labels…and start writing some proper batch scripts.

About these ads

10 thoughts on “A Quick guide to Cygwin commands for the deprived of the DOS world

  1. I know what you mean about things being busy! I thought that you’re supposed to get to relax some and enjoy the holidays, but it never seems to work out that way for me. :)

    Let me put in my vote for anyone still laboring to write DOS/NT batch files to switch to writing bash (or other UNIX-like shells) scripts under Cygwin… Particularly with sed and awk, you can do some really amazing things that are otherwise pretty difficult in DOS.

    Anyway, I wanted to add a note about PuTTY… It’s open source under the MIT license, so there are a ton of both free and commercial products that are based on or incorporate its code. Another one that I found that incorporates PuTTYcyg’s functionality (via some additional files) is KiTTY. It looks interesting, though I had difficulties taming it on my system and switched back to PuTTYcyg pretty quickly.

    Also, since this post is primarily about how to UNIX-in-DOS, I thought I’d point out some efforts to make this possible other than cygwin…

    GnuWin32

    http://gnuwin32.sourceforge.net/

    Easy to grab individual utilities if you just want to add grep, sed, awk, etc… I checked out a couple of utilities once but have essentially no experience with it on the whole. Download/run an installer per utility.

    UnxUtils

    http://unxutils.sourceforge.net/

    Another good package that I used for quite a while. Seems like there were some goofy issues I ran into and so had to hack around a bit to get everything to behave the way I wanted, and I never did get their sh shell to work to my liking… Really easy to ‘install’ everything, just unzip and add to your PATH.

    UWIN

    http://www2.research.att.com/sw/tools/uwin/

    I recomend this one the least… I used it for a while but I don’t remember being particularly happy with how it worked. If I remember correctly, installation was difficult, threw errors, and generally felt buggy. Maybe it’s gotten better in the meantime, I haven’t used it in a few years. That said, at the time it was better than cygwin. :)

    Of the lot, I like cygwin + PuTTYcyg the best. However, if you just want a toolkit of more powerful command-line utilities, GnuWin32 and UnxUtils will let you pick and choose what to add to your DOS environment without superceding it.

    Happy hacking!

  2. thank you for your post,

    another tool which can be used instead of cmd.exe, both for DOS shell and Cygwin is called Console2. I have switched to it for both DOS and Cygwin shells, it can use tabs and other nice features, it is extremely stable. http://sourceforge.net/projects/console/. I warmly recommend it.

    regards,
    Eric

  3. Good Day,

    My question is this,

    i want to write a cygwin script in which clients data information (at the point of writing the script the data have not been collected) would be stored. When the data is therefore collected, i can now open a code for each of my client using the data collected.

    Thank you.

    David

    • David,

      not sure if you want to get the client data into a database or whether you want to hold it in files on the os. If it’s the former, it’s probably worth having a look at the bash scripting site I linked to in the post.
      If you want to put it into a database, you can use the here document syntax.
      There’s an example of this here.

      HTH

      Mike

  4. Really Informative!

    I am new to cygwin, a simple question need to be ask.

    Already downloaded the linux files (.dat, binary files etc.). I have tried the script:

    /cygdrive/c/folder/abc.dat

    but it’s not working. Kindly anyone recommend me on to run a linux file using cygwin.

    Thanks!

    • Daniel,
      I’m not sure that you can do what you’re trying to do… On the cygwin.com home page, they specifically indicate that cygwin is not a way to run Linux binaries on Windows; rather you need to recompile from source under cygwin instead. If you do some searching, sometimes you can find somewhere that provides a version of the package you want, already compiled for cygwin. Also make sure that the package you want isn’t already included in the ports that are accessible inside the cygwin installer.

      If you can describe in more detail what you’re trying to do, or what program you’re trying to run, then maybe we can help further. You might also want to look into using a Linux Live-CD of some distribution, like maybe Ubuntu, though it will require you to reboot.

      https://help.ubuntu.com/community/LiveCD

      You might also consider using a virtualization package, like virtualbox, though that requires a bit of setup and might have a learning curve, albeit a fairly gentle one.

      https://www.virtualbox.org/

    • Harini,

      in general, the easiest way to create a new file is simply to invoke an editor with a new file name.
      For example, to create a file using vi :

      vi test.txt
      

      In the editor type some text and then save the file.

      HTH

      Mike

  5. If am trying to find the length of a line using awk.

    \unix\awk ‘{ Print length($0) }’ < InputFile

    As far as I know, this should work – but it is giving me the CONTENTS rather than the length.

    I have tried various ways, and none seem to work.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s