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….
- Go to http://code.google.com/p/puttycyg/
- Click on the download link and download the file ( in my case, puttycyg-20101029.zip)
- 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.
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!
LikeLike
Thanks again Matt – you certainly seem to have done a fair bit of work in this area.
LikeLike
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
LikeLike
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
LikeLike
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
LikeLike
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!
LikeLike
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/
LikeLike
This is clear but how to create a File in Linux?
LikeLike
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 :
In the editor type some text and then save the file.
HTH
Mike
LikeLike
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.
LikeLike