Tuesday, August 3, 2010

Running Cygwin in Your Current Directory

Most of the time I'm on the command line, I'm using the Windows command prompt. When I need a Bash shell (cygwin), it's really annoying to have to cd all the way back to the directory I was in before calling cygwin.

After locating Martin Gramatke's email to the Cygwin mailing list (Thanks Martin!), I put together an updated cygwin.bat, and .bash_profile in order to let Cygwin remember my working directory.

The first part is a modified cygwin.bat file. I've added c:\cygwin\bin to my PATH variable already, so it is no longer necessary to cd to the c:\cygwin\bin directory just to invoke bash. The below cygwin.bat file no longer changes directories on you, and also stores your current working directory in an environment variable so bash can tell if/where you would like to pick up working once bash has started.

@echo off
setlocal

for /f "usebackq delims=" %%i in (`cygpath "%cd%"`) do set BASHHERE=%%i

bash -li %*

endlocal
Note the handy 'for-piping' of the cygpath command into the BASHHERE variable.

The second part of the process involves telling bash to switch to your 'preferred' directory when your profile is loaded. Adding the following lines to the end of your .bash_profile (~/.bash_profile) will instruct bash to cd to the directory stored in the updated cygwin.bat script so you can seamlessly resume working in the same directory - using Cygwin!
if [ "$BASHHERE" != "" ]; then
cd "$BASHHERE"
fi
I normally put this at the end of the file.

Using both of these changes will mean that whenever you run cygwin using the cygwin.bat script, your currrent working directory will be preserved. If you wish to start bash in your home directory, don't make the call to cygwin.bat, and simply call bash.exe directly (with any options you may want)

Cheers!

Opening a Command Prompt in a Specific Folder

Hi everyone!

I was recently asked about opening a DOS prompt to a given folder and figured I would share the .reg file I keep around for this purpose.

Here it is:
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Folder\shell\Command Here...]

[HKEY_CLASSES_ROOT\Folder\shell\Command Here...\command]
@="cmd /K \"cd %1\""
(Copy, paste, save with .reg extension, run) ^_^

Note that the "Command Here..." option only appears if you right click on the folder you want the prompt to open in. This may mean you have to back out of the directory first so you can right click on it. If anyone's come up with a way around this, I'd be interested in hearing it - comments are welcome!

Sunday, July 25, 2010

Using Cygwin Emacs from DOS prompt

When I'm working in a command line environment in Windows, I normally use notepad for my text editing. On lunix, I prefer emacs. Earlier today I decided it would be nice if I could use emacs in my DOS prompt if I'm in the mood.

By taking advantage of bash's -c flag, it is possible to tell bash to open emacs on the given file(s). After converting the file paths to cygwin appropriate paths, the call is a piece of cake.

I put all this in a bat file on my path so I can call emacs from my DOS prompt at any time:

@echo off
setlocal

set TOEMACS_FILEPATHS=

REM Convert files to full cygwin paths and store in variable
:loopOnInputs
if "%1"=="" goto :callEmacs

REM Handy line for storing the output of a command in a variable
for /f "usebackq delims=" %%i in (`cygpath "%~dpnx1"`) do set ARG_CYGPATH=%%i

REM Store/append the file path in the variable we'll pass to emacs
if "%TOEMACS_FILEPATHS%"=="" (
set TOEMACS_FILEPATHS=%ARG_CYGPATH%
) else (
set TOEMACS_FILEPATHS=%TOEMACS_FILEPATHS% %ARG_CYGPATH%
)

REM Pop the argument we just read
shift
goto :loopOnInputs

REM Run emacs in a new bash shell
:callEmacs
bash -lic "emacs $*" dummy %TOEMACS_FILEPATHS%

:EOF
endlocal


While looping through the input arguments, you'll notice an interesting for loop that I'm using to pipe the output of the cygpath command to a variable. I spent a while trying to figure this out a while ago, and it's been working well for me so far. In short, it loops over every line in the command's output and sets the variable to that line. The delims option changes the delimiter used for separating the command output from spaces and tabs to the end of a line, and since the output of the cygpath command is only one line, we don't have to worry about overwriting the path when there are multiple lines.

Finally, I believe $* is interpreting my dummy argument as $0 or something similar, so that's what the dummy argument is doing there.

Enjoy!

Saturday, July 24, 2010

Listing Hidden Files in Bash

I decided it would be useful to have an alias to display all the hidden files in a directory, but wanted a bit more than just a simple alias to 'ls -Ad .**' as this only allows you to list the current directory. Aliasing 'ls -Ad $*.**' worked, but didn't provide any room for error checking regarding trailing directory slashes. There was also the grep option, but that messes with the nice column formatting ls provides so I scrapped that idea.

In short, I decided to write up a function with a short name that I could use as an alias:

# list only hidden files in the given directory(s)
function lh() {

# if directories were given
if [ $# -gt 0 ]; then

# store current dir so we can come back
startingPath=`pwd`

# loop through input dirs
for i in $*; do

# only list contents for directories
if [ -d $i ]; then
cd $i # cd to the directory
echo $i: # print a header
ls -Ad .** # list hidden files
else
echo Ignoring directory: $i
fi

echo # blank line for readability

done

# cd back to your original directory
cd $startingPath

else

# just list hidden files for current directory
ls -Ad .**

fi
}

First post!

First post!
Hi all! I've decided to put up this blog to share some of the handy tricks I've come across while working on scripts that you guys might find useful as well. I'm not sure what I'll do about posting some of the scripts I've already come up with, but as I write up new ones, I'll try to post them here. Keep an eye out for interesting coding tidbits as well!