bash

All posts tagged bash

I recently needed to keep a Bash script in a centralized location, with many symbolic links to that script sprinkled throughout my repository. I wanted the script be able to determine both the user’s PWD, as well as the true location of the script. Based on all the different suggestions found online, I created a little test script to see how well each suggestion worked:

#!/bin/bash

echo "\$0"
echo $0
echo ""

echo "pwd -P"
pwd -P
echo ""

echo "pwd -L"
pwd -L
echo ""

echo "which \$0"
which $0
echo ""

echo "readlink -e \$0"
readlink -e $0
echo ""

echo "readlink -e \$BASH_SOURCE"
readlink -e $BASH_SOURCE
echo ""

I put this script (test.sh) in ~/ and then created a symlink to it in a different directory. Here are the results.

My friend JT left a comment below to say that using $BASH_SOURCE is probably the better choice than using $0, since $0 can be changed, and is only set equal to the file name by convention.

Directly calling the script from the same directory (/home/matthew/):

matthew@broderick:~$ ./test.sh
$0
./test.sh

pwd -P
/home/matthew

pwd -L
/home/matthew

which $0
./test.sh

readlink -e $0
/home/matthew/test.sh

Directly calling the script from some other directory (/some/other/directory/):

matthew@broderick:~/some/other/directory$ ~/test.sh
$0
/home/matthew/test.sh

pwd -P
/home/matthew/some/other/directory

pwd -L
/home/matthew/some/other/directory

which $0
/home/matthew/test.sh

readlink -e $0
/home/matthew/test.sh

Creating a symlink to ~/test.sh in ~/some/other/directory, and calling it directly (./test.sh):

matthew@broderick:~/some/other/directory$ ln -s ~/test.sh ./test.sh
matthew@broderick:~/some/other/directory$ ./test.sh
$0
./test.sh

pwd -P
/home/matthew/some/other/directory

pwd -L
/home/matthew/some/other/directory

which $0
./test.sh

readlink -e $0
/home/matthew/test.sh

Creating a symlink to ~/test.sh in ~/some/other/directory, and calling it from yet another location:

matthew@broderick:~/some/other/directory$ ln -s ~/test.sh ./test.sh
matthew@broderick:~/some/other/directory$ cd ~/somewhere/else
matthew@broderick:~/somewhere/else$ ~/some/other/directory/test.sh
$0
/home/matthew/some/other/directory/test.sh

pwd -P
/home/matthew/somewhere/else

pwd -L
/home/matthew/somewhere/else

which $0
/home/matthew/some/other/directory/test.sh

readlink -e $0
/home/matthew/test.sh

Conclusion:
So, it looks like “readlink -e $0” will always return the full, non-symlink, “physical” location of the script (regardless of whether or not symlinks are involved). Looks like “pwd” returns the user’s current working directory reliably.

As part of my work with Wayne and Layne, Adam and I do a lot of work together remotely, since I live in Pennsylvania and he lives in Minnesota. It’s really nice to be able to quickly share a work in progress, whether it be a diagram in Inkscape or a printed circuit board layout in Kicad. Setting up a Skype or other screen sharing system incurs too much transaction cost and isn’t very quick, so I was looking for something quicker and simpler.

I wrote this little script to take a screenshot of my entire display, add a timestamp to the bottom, and automatically upload it to my website. I set up an SSH key between my computer and my webserver (that is unlocked when I login), and added the following script to my path as screenshot_poster.sh

#!/bin/bash
#
# This script will capture the whole screen
# and upload it to the web in a known location
# Written by Matthew Beckler for Wayne and Layne, LLC
# Last updated August 31, 2012

cd /tmp
import -window root temp.png
WIDTH=`identify -format %w temp.png`
DATE=`date`
convert -background '#0008' -fill white -gravity west -size ${WIDTH}x30 caption:"$DATE" temp.png +swap -gravity south -composite screenshot.png
scp screenshot.png user@example.com:/var/www/rest/of/the/path/to/screenshot.png

DEST="http://example.com/path/to/screenshot.png"
# do you want a notification or to just open the browser?
#notify-send -t 1000 "Screenshot posted" "$DEST"
xdg-open "$DEST"

The final two lines allow you to make a little desktop notification of the URL, open a web browser to the image’s location, or both. Someday I will set up a nice keyboard shortcut to run this script, to make the process of sharing my work-in-progress as quick and easy as possible.

screenshot

If you’ve ever uploaded a folder full of images to your web server, seeing the directory listing of all the filenames is less than ideal, as you can’t preview any of the images without clicking through on them. Here is a quick one-liner to generate an index HTML page for all the images:

for i in *.jpg; do echo "<img src=\"$i\" width=\"640\" /><br />" >> index.html; done

Unfortunately, that will cause your browser to load up the full-size version of every image into RAM. If you’ve got a lot of photos, especially if they are very large files straight from your DSLR, you’ll probably start swapping. To fix this, we first use the mogrify command from the ImageMagick suite to generate thumbnails from all your images. Here, we assume that your source images are all in JPEG format, so we can easily use identically-named PNG files for our thumbnails:

mogrify -format png -thumbnail 640 *.jpg

Then, we can use a slightly-modified version of the loop above to generate the HTML:

for i in *.jpg; do BASE="`basename "$i" .jpg`"; echo "<a href=\"$i\"><img src=\"$BASE.png\" /></a><br /><br />" >> index.html; done

Adjust the size of the images by changing the “640” above to whatever image width you like.