Tips and Tricks About Computers, Web Development, Linux, the Internet and the Like
Posts tagged Bash
Random cow(ish) animals preaching quotes on Ubuntu 9.10
Feb 3rd
Looking for something interesting when I login to one of my servers, I decided to whip up the following script I appended to my ~/.bashrc file.
# fortune and cowsay are needed for the snippet to work, I had to install these first sudo apt-get install fortune cowsay
COWDIR=/usr/share/cowsay/cows/; COWNUM=$(($RANDOM%$(ls $COWDIR | wc -l))); COWFILE=$(ls $COWDIR | sed -n ''$COWNUM'p'); fortune | cowsay -f $COWFILE
UPDATE:
Suggested by MrBougo, a shorter but perhaps more process intensive method:
fortune | cowsay -f $(ls /usr/share/cowsay/cows/ | shuf | head -n1)
Breaking down the script, the first 3 parts create variables and the last command executes the cowsay and quote.
# defines the directory of the cow files COWDIR=/usr/share/cowsay/cows/; # Get a random number limited to the number of files in the directory, making clever use of % (mod) and adding 1 to make sure it doesn't return 0 COWNUM=$(($RANDOM%$(ls $COWDIR | wc -l))+1); # list the contents of the cow dir again, pipe to sed and use the number as a random line to get the name of a file COWFILE=$(ls $COWDIR | sed -n ''$COWNUM'p'); # use fortune to get a quote, pipe to cowsay and use the file as defined above fortune | cowsay -f $COWFILE;
Finding the difference in time between the first and last file in a folder using bash
Aug 22nd
I was working on running some statistics on log files and it required me to figure out the difference to increase the accuracy. I came up with the following bash script:
#!/bin/bash # get the dates start_date=$(date --utc --date "$(ls -Rt --full-time | tail -n1 | awk '{ print $6 }')" +%s) end_date=$(date --utc --date "$(ls -Rt --full-time | head -n2 | tail -n1 | awk '{ print $6 }')" +%s) # find the difference difference=$((end_date-start_date)) # echo results echo $end_date - $start_date = $difference seconds echo $((difference/86400)) days
Which I originally wrote as a one liner:
start_date=$(date --utc --date "$(ls -Rt --full-time | tail -n1 | awk '{ print $6 }')" +%s); end_date=$(date --utc --date "$(ls -Rt --full-time | head -n2 | tail -n1 | awk '{ print $6 }')" +%s); difference=$((end_date-start_date)); echo $end_date - $start_date = $difference seconds; echo $((difference/86400)) days;
I got a little carried away and created this beast, which still isn’t as accurate as I need it to be but it did give me some information:
map_1=nordiccastle;map_2=dance;start_date=$(date --utc --date "$(ls -Rt --full-time | tail -n1 | awk '{ print $6 }')" +%s); end_date=$(date --utc --date "$(ls -Rt --full-time | head -n2 | tail -n1 | awk '{ print $6 }')" +%s); difference=$((end_date-start_date)); echo $... Read Moreend_date - $start_date = $difference seconds; echo logs for $((difference/86400)) days; map_1_ended=$(find -name *00*.log | xargs egrep -A 4 "endmatch|timelimit -1" |grep $map_1 |wc -l); map_1_played=$(find -name *00*.log | xargs egrep "gamestart" |grep $map_1 |wc -l); echo $map_1 endmatched $map_1_ended out of $map_1_played times played; map_2_ended=$(find -name *00*.log | xargs egrep -A 4 "endmatch|timelimit -1" |grep $map_2 |wc -l); map_2_played=$(find -name *00*.log | xargs egrep "gamestart" |grep $map_2 |wc -l); echo $map_2 endmatched $map_2_ended out of $map_2_played times played
It was used to see how many times a map was played and how many times it was voted to end the match.
It should really be a separate script to allow for more organization
Generating sequences of numbers or characters with bash
Aug 15th
If you ever needed to generate a sequence of characters or numbers, the terminal (using bash) is a quick and easy way to do it. Lets explore some examples bash’s brace expansion:
$ echo {a..z} a b c d e f g h i j k l m n o p q r s t u v w x y z
by defining a start and end character with the ‘..’ in between, we tell bash to fill in the rest and echo a list for us. Those are all lowercase, what if you wanted uppercase? simple:
$ echo {A..Z} A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Or both, with a few extra characters in the mix:
$ echo {A..z} A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z
It doesn’t always have to be a-z though,
$ echo {A..G} A B C D E F G
This also works with numbers:
$ echo {0..9} 0 1 2 3 4 5 6 7 8 9 echo {0..100} 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
Descending as well as ascending
$ echo {9..0} 9 8 7 6 5 4 3 2 1 0
There is another method to generate a sequence of numbers from the command line, rightfully called ‘seq’
$ seq 1 5 1 2 3 4 5
The difference here is that it’s delimited by a new line, however, we can override that with the -s (seperator) flag
$ seq -s " " 1 10 1 2 3 4 5 6 7 8 9 10
Finding files and strings using the terminal in Linux
Feb 4th
My favorite thing about Linux is the terminal. I use it countless times a day to do all sorts of tasks, like managing game servers or writing scripts to do tedious tasks. One of the most popular things I do in the terminal is search for files or strings inside of files and today I’d like to go over a few methods and tricks for doing this. There are three tools that make this task amazingly easy but combining them is where we find the real power. These three tools are locate, find and grep. I will cover the basic use of these tools with some examples and tricks but I suggest you take a look at the man pages for the tools for addition information (i.e. man locate).
locate
Locate has got to be the most straight forward way to search for files. It uses a database so it’s blazing fast when searching your entire computer, compared to the ‘find’ we’ll cover later. It’s not available by default on all Linux distributions (it is on Ubuntu) so you might have to install it. Since I’ll be mentioning fstab later, I’ll give my examples with it.
Basic syntax is: locate [filename]
tyler@quadjutsu:~$ locate fstab /etc/fstab /etc/fstab.orig /etc/fstab.pre-ntfs-config /etc/fstab~ /usr/include/fstab.h /usr/lib/udev/migrate-fstab-to-uuid.sh /usr/share/apps/katepart/syntax/fstab.xml /usr/share/doc/m4/examples/fstab.m4 /usr/share/doc/mount/examples/fstab /usr/share/doc/util-linux/examples/fstab.example2 /usr/share/man/man5/fstab.5.gz /usr/share/pysdm/fstab.py /usr/share/pysdm/fstab.pyc
This database will automatically update itself at various times but to force an update type the following command:
tyler@quadjutsu:~$ sudo updatedb
Folder exclusions can be found (and edited) in /etc/updatedb.conf
By default (at least in ubuntu) /media (your mounted media) is not included in this database. This means if you use extra drives you’ve added to your computer and you want them to be searchable through the locate tool, you’ll have to mount them to a directory like /mnt.
To mount a drive on boot, you’ll need to add a line like the following to your /etc/fstab. The one below mounts an ntfs drive to /mnt/mydrive. That folder must exist for the drive to be mounted.
/dev/sda1 /mnt/mydrive ntfs-3g defaults,locale=en_US.utf8 0 0
I found the /dev/sda1 part by listing my harddrive partitions using the following command:
sudo fdisk -l
find
Find is a little more cryptic than locate but it’s a very powerful tool that should be available on most Linux distributions if not all.
Basic syntax is: find [directory] -name “[string]” -print
Find will search recursively through the folder you’re calling it from. The directory isn’t required but it will show you the full path. A neat trick is to use $(pwd) which creates a string for the “present working directory”. It’s also a good habit to use quotes around your name search because you can’t do regular expressions without it. find does not do matching the same way locate does. You’ll have to specific a wild card (*) for partial searches.
tyler@quadjutsu:~/Desktop$ find -name "notes" -print tyler@quadjutsu:~/Desktop$ find -name "notes*" -print ./notes.txt~ ./notes.txt tyler@quadjutsu:~/Desktop$ find $(pwd) -name "notes*" -print /home/tyler/Desktop/notes.txt~ /home/tyler/Desktop/notes.txt tyler@quadjutsu:~/Desktop$ find -name "no[a-z]*" -print ./notes.txt~ ./notes.txt
My Buddy From Belgium, MrBougo has asked I make note that -iname makes it case insensitive.
grep
In the context of searching, grep is like a pocket knife. It’s great for limiting returned results and searching through files, which are my two most common uses of it, though I’m sure there are a million others. First I’ll cover the searching files for strings portion and in combined tools we’ll discuss how to refine search results.
In terms of searching strings in files, basic syntax is: grep “[string]” [filename]
grep is case sensitive but can be changed to insensitive with -i. You can access extended regular expressions (which allow for such functions as use of the + sign to signify 1 or more characters) by calling “egrep”
tyler@quadjutsu:~$ grep "tyler" resume.txt tyler@detrition.net tyler@quadjutsu:~$ grep "Tyler" resume.txt Tyler J. Mulligan tyler@quadjutsu:~$ grep -i "tyler" resume.txt Tyler J. Mulligan tyler@detrition.net tyler@quadjutsu:~$ grep -i "tyl" resume.txt Tyler J. Mulligan tyler@detrition.net tyler@quadjutsu:~$ egrep -i "tyler [a-z.]+" resume.txt Tyler J. Mulligan tyler@quadjutsu:~$ egrep "tyler [a-z.]+" resume.txt
MrBougo also mentioned that, grep returns a 1 exit status if it doesnt find, so grep “foo” && grep “bar” will only grep for bar when foo is found.
Combining the tools
There are two very important techniques for linking together commands in the terminal. The pipe | and &&. The pipe passes the output of one command to the next, the && runs a command after the one before is complete.
Starting off slow, we’ll refine our search of grep with another grep. Note that you don’t have to use the quotes as I’ve shown below.
tyler@quadjutsu:~$ grep -i "nexuiz" resume.txt * Web Developer and Interaction Designer for Nexuiz / Alientrap * Owner and Creator of Nexuiz Ninjaz tyler@quadjutsu:~$ grep -i "nexuiz" resume.txt |grep -i ninjaz * Owner and Creator of Nexuiz Ninjaz
Not that you would really want to do the follow commands but to emphasize how | and && work, the following example shows how you’re running the command twice rather than refining a search:
tyler@quadjutsu:~$ grep -i "nexuiz" resume.txt && grep -i "ninjaz" resume.txt * Web Developer and Interaction Designer for Nexuiz / Alientrap * Owner and Creator of Nexuiz Ninjaz * Owner and Creator of Nexuiz Ninjaz
Recalling our first example with fstab, there was a lot of extra results we didn’t want. We know know it was in the etc folder, so we can filter our results by that.
tyler@quadjutsu:~$ locate fstab |grep etc /etc/fstab /etc/fstab.orig /etc/fstab.pre-ntfs-config /etc/fstab~
Another way would be to EXCLUDE folders we don’t want with the -v flag.
tyler@quadjutsu:~$ locate fstab |grep -v usr /etc/fstab /etc/fstab.orig /etc/fstab.pre-ntfs-config /etc/fstab~
And filtering out the junk like so:
tyler@quadjutsu:~$ locate fstab |grep etc |grep -v "~" |grep -v "\." /etc/fstab
~ has a special meaning in the terminal so you must quote it to match it. ~ refers to the user’s home directory, in this case /home/tyler. I’ve also had to escape . because it too has special meaning, in the context of regular expressions, it will match any character… if we’re excluding any character, we’re excluding our results
.
Quick Tricks
Remember commands is sometimes a hard thing to do, especially when it’s a whole string of complicated commands and regexes. Sometimes, I know I don’t have the mind to take notes but that’s okay (for a grace period) because bash keeps track for me. The history command will list all your recently executed commands and utilizing the grep command, we can filter that list.
tyler@quadjutsu:~$ history |grep locate 613 locate fstab 614 locate fstab |grep etc 624 locate fstab |grep etc |grep -v "~" |grep -v "\."
A quick way to search for files in a directory would be to use locate as the path and grep the results
tyler@quadjutsu:~$ locate ~ |grep notes.txt /home/tyler/Desktop/notes.txt
These are the basics of finding files and searching through them. Linux provides many tools to reformat and replace strings. There are a million different ways to combine commands and always a faster way to do it. Keep playing and you’ll just get better and better.
Ubuntu Window Management with Multiple Monitors, Window Effects and Default File Associations
Nov 25th
Multiple Monitors Window Management in Ubuntu
Moving your applications from one monitor to the next with hotkeys
I’ve been using multiple monitors for a while now, Starting with a 17″ CRT with a 19″ CRT and moving up to two 19″ LCD, then 3, then temporarily one wide screen and back to 2. Something I always loved having as a utility in ultramon that I couldn’t find in Ubuntu (Gnome) or any window manager for that matter, was the ability to move applications from monitor to monitor. I had assumed the search futile until I was searching about some questions I had concerning Compiz-fusion with dual monitors and I came about this thread on Ubuntu forums which brightened up my day. A fellow named gfixler posted a bash script that utilizes command line applications to move the windows.
For you multi-monitor users seeking salvation from removing your hand from the keyboard to move your application from one monitor to another, here’s the skinny on getting it setup using compiz-fusion, aka Advanced Desktop Effects, to set my keybinds.
1. Open a terminal and setup your prerequisites with apt-get:
sudo apt-get install wmctrl xprop xwininfo
If you get errors about x11-utils, just ignore them, this package will handle your needs.
2. Next, lets put the script somewhere you can call it, say “~/scripts”
mkdir ~/scripts && cd ~/scripts && touch movewin.sh && chmod +x movewin.sh && gedit movewin.sh
2. Paste the following code, find the first function “getNumberOfMonitors” and configure it to the number of monitors you have (default 2).
#!/bin/bash # swap_monitor.sh (original version) # Moves the active window to the other screen of a dual-screen Xinerama setup. # # movewin.sh (modified version) # allows movement of windows left and right between multiple monitors # # Requires: wmctrl, xprop, xwininfo # # Original Author: Raphael Wimmer # raphman@gmx.de # # Modified by: Gary Fixler # gfixler+bash@gmail.com function getNumberOfMonitors { # simply must be hardcoded # e.g. MatroxTripleHead2Go can service 3 screens, # but appears as only one monitor to the computer # change to your number of monitors echo 2 } function getMonitorWidth { numberOfMonitors=$(getNumberOfMonitors) monitorLine=$(xwininfo -root | grep "Width") monitorWidth=$((${monitorLine:8}/$numberOfMonitors )) echo $monitorWidth } function getActiveWindowID { activeWinLine=$(xprop -root | grep "_NET_ACTIVE_WINDOW(WINDOW)") activeWinID="${activeWinLine:40}" echo $activeWinID } function getActiveWindowHorizontalPosition { activeWinID=$(getActiveWindowID) xPosLine=$(xwininfo -id $activeWinID | grep "Absolute upper-left X") xPos=${xPosLine:25} echo $xPos } function getActiveWindowWidth { activeWinID=$(getActiveWindowID) xWidthLine=$(xwininfo -id $activeWinID | grep "Width") xWidth=${xWidthLine:8} echo $xWidth } function getActiveWindowCurrentMonitor { numberOfMonitors=$(getNumberOfMonitors) monitorWidth=$(getMonitorWidth) activeWinID=$(getActiveWindowID) xPos=$(getActiveWindowHorizontalPosition) i="0" while [ $xPos -gt $monitorWidth ] do xPos=$[$xPos-$monitorWidth] i=$[$i+1] done echo $i } function getActiveWindowPositionOneMonitorToTheLeft { monitorWidth=$(getMonitorWidth) currentMonitor=$(getActiveWindowCurrentMonitor) activeWinID=$(getActiveWindowID) xPos=$(getActiveWindowHorizontalPosition) xPos=$[$xPos-$monitorWidth] echo $xPos } function getActiveWindowPositionOneMonitorToTheRight { monitorWidth=$(getMonitorWidth) numberOfMonitors=$(getNumberOfMonitors) currentMonitor=$(getActiveWindowCurrentMonitor) activeWinID=$(getActiveWindowID) xPos=$(getActiveWindowHorizontalPosition) xPos=$[$xPos+$monitorWidth] echo $xPos } function changeActiveWindowMonitor { activeWinID=$(getActiveWindowID) if [ $1 -eq "0" ] then newXPos=$(getActiveWindowPositionOneMonitorToTheLeft) newXPos=$[$newXPos-5] else newXPos=$(getActiveWindowPositionOneMonitorToTheRight) newXPos=$[$newXPos-5] fi winState=$(xprop -id ${activeWinID} | grep "_NET_WM_STATE(ATOM)" ) if [[ `echo ${winState} | grep "_NET_WM_STATE_MAXIMIZED_HORZ"` != "" ]] then maxH=1 wmctrl -i -r ${activeWinID} -b remove,maximized_horz fi if [[ `echo ${winState} | grep "_NET_WM_STATE_MAXIMIZED_VERT"` != "" ]] then maxV=1 wmctrl -i -r ${activeWinID} -b remove,maximized_vert fi if [[ `echo ${winState} | grep "_NET_WM_STATE_FULLSCREEN"` != "" ]] then fulls=1 wmctrl -i -r ${activeWinID} -b remove,fullscreen fi # move window (finally) wmctrl -i -r ${activeWinID} -e 0,${newXPos},-1,-1,-1 # restore maximization ((${maxV})) && wmctrl -i -r ${activeWinID} -b add,maximized_vert ((${maxH})) && wmctrl -i -r ${activeWinID} -b add,maximized_horz ((${fulls})) && wmctrl -i -r ${activeWinID} -b add,fullscreen # raise window (seems to be necessary sometimes) wmctrl -i -a ${activeWinID} } function moveActiveWindowOneMonitorToTheLeft { changeActiveWindowMonitor 0 } function moveActiveWindowOneMonitorToTheRight { changeActiveWindowMonitor 1 } "$1" exit 0
3. Setup your hot keys with compiz-fusion. Go to System >> Preferences >> Advanced Desktop Effects. Inside “General Options“, click on the command tab (I apologize for my heinous blue links).
Use
scripts/./movewin.sh moveActiveWindowOneMonitorToTheRight
and
scripts/./movewin.sh moveActiveWindowOneMonitorToTheLeft
respectively
Per Application Window Effects in Ubuntu
Bring character and tickle your soul with per application window effects
Another cool feature Compiz-fusion has is window animations. My friend James Lindsay recently reminded me about Window Effects… which when I first install Ubuntu on my laptop, I experimented my butt off… but being a laptop… I just used simple ones I’d turn off half the time anyway. He asked me why I don’t use them on my desktop and I didn’t have a good reason. Well, now I have 2 good reasons to keep using compiz.
I made my Thunderbird use the airplane effect so when I send emails, it flys away and for Geany, I used the magic lamp for open, close, maximize and minimize (different speeds). It’s a fun little effect that breaks up the stiffness of the desktop.
Default File Associations in Ubuntu
geany > gedit
I was tired of gedit popping up when geany’s just as lightweight but more affective. So found a command and altered it a bit to make my default editor geany.
1. Open the terminal and create\open the following file:
gedit ~/.local/share/applications/defaults.list
If it’s blank, add “[Default Applications]“. If it’s not, find “[Default Applications]“.
2. Then, back to the terminal, grep the default files associations and replace gedit with your editor of choice
grep gedit /usr/share/applications/defaults.list | sed s/gedit/geany/g
Copy (ctrl+shift+c) and paste the output into gedit, below the “[Default Applications]” header.
3. Restart nautilus to load the changes (will close all your file managers that are open and blink/freeze your desktop for a second)
pkill nautilus
Good luck, have fun and happy coding



