Today I Learned

A Hashrocket project

121 posts about #command-line

Redirect outputs with subshell

Today I learned how to use a Subshell to redirect multiple outputs as a single one. This way I can run a bunch of commands and unify all the results as it was a single command.

(git diff --name-only; git diff --staged --name-only) | sort -u

The above example will show me a sorted list of changed files (including the staged ones) in a git project without duplicates.

Here's another example:

$ echo "world"; echo "hello" | sort -u
#=> world
#=> hello

$ (echo "world"; echo "hello") | sort -u
#=> hello
#=> world

Shhh.... Curl silently.

The curl program generally displays a progress bar as its making a request and receiving a response. This can be awkward when you are trying to wrap curl programmatically.

To shut off the progress bar use:

curl -sS http://www.google.com

The first option (-s) hides the progress bar and the errors. The second option (-S) will expose an error on fail if used in conjunction with -s.

List Available File Types For Ack

The ack utility allows you to filter the searched files based on file type. If you'd like to know all of the file types available, you can use the --help=types flag. This will include file types you've specified in your .ackrc file.

Here is a sample of some of the output.

$ ack --help=types
    ...
    --[no]css          .css .less .scss
    --[no]dart         .dart
    --[no]delphi       .pas .int .dfm .nfm .dof .dpk .dproj .groupproj .bdsgroup .bdsproj
    --[no]elisp        .el
    --[no]elixir       .ex .exs
    --[no]erlang       .erl .hrl
    --[no]fortran      .f .f77 .f90 .f95 .f03 .for .ftn .fpp
    --[no]go           .go
    --[no]groovy       .groovy .gtmpl .gpp .grunit .gradle
    --[no]haskell      .hs .lhs
    --[no]hh           .h
    --[no]html         .html .mustache .handlebars .tmpl
    --[no]jade         .jade
    --[no]java         .java .properties
    --[no]js           .js
    ...

See man ack for more details.

ack --bar

The ack utility has a fun Easter egg that dumps a Star Wars meme to the command line. Give it a try.

$ ack --bar

See man ack for more details.

Extended file attributes on macOS

You can store metadata on any file in the mac filesystem(HFS+). If you want to ensure the file has a specific encoding, or if you want to place a checksum with the file you can use file attributes.

Setting and reading are easy on macOS with the xattr utility:

> touch something.txt
> xattr -w xyz 123 something.txt
> xattr -p xyz something.txt
123

In this example we wrote(xattr -w) an attribute onto the file and printed it(xattr -p) to see that it was written.

You can list the file attributes with a cryptic option for ls, ls -l@. Try doing this on your ~/Downloads dir to learn something cool about how macOS treats files coming from the internet.

Bits of Characters

If you are curious what the binary of an ascii/utf-8 char is you can use this string of commands at the command line:

echo 'A' | xxd -b

The A character is 65 in ascii which is 64 + 1. 01000000 is 64. 00000001 is of course 1, 01000001 is 65.

echo 'a' | xxd -b

The a character is 97 in ascii which is 64 + 32 + 1. 00100000 is 32 in binary, given this and the above, 01100001 is 97.

echo 'πŸ€“' | xxd -b

This ridiculous emoji is a utf-8 char. When you look at the binary for it:

11110000 10011111 10100100 10010011

You can see that every byte begins with a 1 which means that it will combine with any subsequent byte beginning with 1 to form a unique character.

Fuzzy awesome copy to sys clipboard w/yank & fzf

Say you want to copy a pid of a process to system clipboard, you could run ps ax, maybe grep on the result, connect your trusty mouse and try to select the value and hit ⌘ + c.

Or you can use the amazing fuzzy finder FZF (brew install fzf) in combination with Yank (brew install yank).

ps ax | fzf | yank

Now simply start typing the name of the process. When you press return you will get the columns broken down into a selectable prompt - choose one and press return. It is now in your system clipboard.

Here's a demo:

demo

This will work with any column spaced or even multiline response. Try running ps ax | yank.

Detach other users in tmux

If someone else has attached to your tmux session but by doing so shrank the tmux screen to a small size, then you are well within your rights to kick them out and regain your real estate.

<leader>D will present you with all the connections. The selection you make will be detached from the current tmux session.

Get the starting hex chars of a binary file

The starting 2 to 8 bytes are used at times to identify the file type of a binary file. You can see what those bytes are in hex format with the xxd command.

> xxd -len 8 beach.png
00000000: 8950 4e47 0d0a 1a0a                      .PNG....

xxd is a command used to create hex dumps.

Convert binary to decimal at the command line

If you have a binary number that you'd like to see in decimal form you can run the command:

> printf '%d\n' 0b10001001
137

First and last arguments to a command line command

If I start with the command:

> echo a b c
a b c

Sometimes I want the last argument to a command, which in this case is c but many times can be a long file path or a hard to spell word. In that case I would use !$:

> echo !$
c

This substitutes !$ with the last argument of the previous command.

To substitute the first argument instead, use !^ like so:

> echo !^
a  

The ^ character and the $ character are ofter used as first and last. In vim those commands move the cursor to the beginning and the end of the line respectively. In regex those characters match the beginning or end of the line.

Search Files Specific To A Language

The ack command makes it easy to narrow the set of searched files to those of a specific programming language. For instance, if you have a rails project and only want to search the ruby files, use the --ruby flag with your ack command.

$ ack --ruby Active

With the --ruby flag, I get a manageable number of results. Without it, not so much.

$ ack --ruby Active | wc -l
      26
$ ack Active | wc -l
    5253

See man ack for more details.

A Better File Wiper πŸ“‚

A tried-and-true debugging technique is to tail the test log:

$ tail -f log/test.log

When the output gets noisy, we might 'wipe' the log by removing it, so that it only contains the output from a single action:

$ rm log/test.log && rspec spec/features/user_logs_in_spec.rb

A better way to do this is to overwrite the file, like so:

$ echo '' > log/test.log

This wipes the file without replacing it, which preserves its serial number. It's less destructive, and allows other processes interacting with the file to finish their work.

Here's an example of this principle in action, using ls -i. Notice how the file's serial number changes when we replace the file, but not when we ovewrite it.

$ ls -i *.txt
27232432 foobar.txt
$ rm foobar.txt
$ touch foobar.txt
$ ls -i *.txt
27232453 foobar.txt
$ echo '' > foobar.txt
$ ls -i *.txt
27232453 foobar.txt

h/t Brian Dunn

Capitalized Letter is the Default

Today I learned something fun about command line interfacesβ€” when presented with a list of choices such as yes, no, or quit, the capitalized choice is the default in many Unix-based CLIs.

Here's some aptitude:

% sudo apt-get install whatever
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  python-cssselect python-glade2 python-pyquery
0 upgraded, 3 newly installed, 0 to remove and 43 not upgraded.
Need to get 497 kB of archives.
After this operation, 2,207 kB of additional disk space will be used.
Do you want to continue? [Y/n]

The interface waits for your Y ('yes') or n ('no').

Because 'yes' is capitalized, it's the default, simply pressing ENTER is the same as pressing Y, then ENTER. Enjoy your extra keystrokes!

Pipe | after | grep

The grep command may not work properly if you want to pipe another command after it, specially when you are tailing a file for example. Just call grep with --line-buffered

heroku logs -t | grep --line-buffered "heroku\[router\]" | awk '{print $11" "$5}'

This command outputs an easy-to-read performance log for each HTTP request:

service=266ms path="/api/posts"
service=142ms path="/api/users"

Run a shell command in the backround

Appending & to a shell command will run it in the background:

#foo.rb
sleep 10
puts 'fin!'
$ ruby foo.rb &
[1] 14485
# can do whatever as we aren't blocked by Ruby sleeping
$ fin !

[1]  + done       ruby foo.rb

Shell ! command

!! is well known to repeat the last shell command in a *nix terminal, it turns out there are other useful variants:

Given a shell history:

$ history
10034  echo $PATH
10035  history
10036  type ruby
10037  which ruby
10038  history
10039  ls

!n - execute a specific item:

$ !10039
ls
Applications
Desktop
...

!?<match>?: matches a pattern and runs the first command that matches:

$ !?uby?
type ruby
ruby is /Users/jason/.rvm/rubies/ruby-2.2.2/bin/ruby

Verify downloaded files from the web #security

If you download a file from the web on a public WiFi and want to run on your machine you might want to check if the file has not been tampered with by a man-in-the-middle-attack or if the file host has been breached.

The easiest way to do this is to check the publised md5 or sha-1 hash for that file (you can do that via your phone if you want to be extra secure). Not every package publishes that but if they do it will be on their website usually next to the download link.

To verify the file you will need to hash the file you downloaded using openssl. For example:

 $ openssl sha1 Kali-Linux-2016.1-vm-amd64.7z
 SHA1(Kali-Linux-2016.1-vm-amd64.7z)= 2b49bf1e77c11ecb5618249ca69a46f23a6f5d2d

Which matches the site's published sha-1 hash:

kalisha

If you want to check md5, simply replace sha1 in the command with md5.

non recursive find

The find command is recursive by default. Let's say you want to find all the screen shots on your ~/Desktop, but ignore any screens in the directories in Desktop. Setting the maxdepth flag will tell how far to recurse, using the value 1 only searches the directory you specified, using 2 would go into each directory, but only not search any sub directories, and so on.

#this will recurse by default
$ find ~/Desktop -name "*Screen*"

#this will only search the Desktop and it's immediate subdirectories
$ find ~/Desktop -maxdepth 2 -name "*Screen*"

Jump To The Ends Of Your Shell History

There are all sorts of ways to do things in your shell environment without reaching for the arrow keys. For instance, if you want to move up to the previous command, you can hit Ctrl-p. To move down to the next command in your shell history, you can hit Ctrl-n.

But what if you want to move to the beginning and end of your entire shell history?

Find your meta key (probably the one labeled alt) and hit META-< and META-> to move to the end and beginning of your shell history, respectively.

source

zsh variable editing

Lets say I made a typo in an important environment variable and I wanted a quick fix, just to see if yes, that was indeed why my application wasn't working.

$ echo $RAILS_ENV
> porduction
# ^^^ YIKES ^^^

The Z shell has a builtin program called vared that helps you edit an existing environment/shell variable.

$ vared RAILS_ENV
porduction

Now you are in an editing context, you can edit the value with all your configured command line editing tools. Fix the error, hit RETURN, and you're good!

List Names Of Files With Matches

I often use grep and ag to search for patterns in a group or directory of files. Generally I am interested in looking at the matching lines themselves. However, sometimes I just want to know the set of files that have matches. Both grep and ag can be told to output nothing more than the names of the files with matches when given the -l flag.

This can come in particularly handy if you just want a list of files that can be piped (or copied) for use with another command. This eliminates all the extra noise.

h/t Dillon Hafer

whois that url?

Let's say you just got a spammy text message that contains a suspicious url and you want to learn more but clicking the link just seems like a bad idea.

You can learn more from the whois program that comes installed on macosx. It sends queries to databases that store domain registration information.

When you use the command:

whois spam.com

You can see the important result

Registrant Organisation: Hormel Foods Corporation

The wikipedia article for whois contains some deep internet history.

Grep through compressed (gzipped) log files

The logrotate linux utility automatically compresses your ever-growing production log files.

If you encountered an error and wanted to search the history including all compressed logs, you may have considered unzipping all of them into a directory and run a grep in that directory.

Fortunately linux offers a more idiomatic way for grepping gzipped files: zgrep.

From the manual:

zgrep, zegrep, and zfgrep act like grep, egrep, and fgrep, respectively, but accept input files compressed with the compress(1) or gzip(1) compression utilities.

h/t Jack Christensen

Test out your zsh prompt

If you are trying to change or create a new prompt in Z shell you can use the print command with the -D flag to help you iterate.

print -P %B%n%b

This prints out your user name in bold to stdout.

Tail Multiple Logs at Once

If you have the following files in your /log:

/erlang.log.1, /erlang.log.2, /erlang.log.3, /erlang.log.4

And you don't know which to watch, just tail them all:

$ tail -f log/erlang.log.*

Alternativly, you can pass it multiple files:

$ tail -f log/erlang.log.1 log/erlang.log.2

ZSH Glob Exclusion

I want to list everything except a .jpg file from the files

foo.doc foo.gif foo.jpg

but if I use print -l * I get them all back. To exclude a pattern in zsh you first must turn on extendedglob.

$ setopt extendedglob

Then, everything after the ^ will be treated as an exclusion.

$ print -l ^*jpg
foo.doc
foo.gif

Encrypting with gpg

Encrypting and decrypting is easy with gpg.

To encrypt the text ABC and write it to a file called abc.enc:

$ echo "ABC" | gpg --symmetric --force-mdc > abc.enc

To decrypt the abc.enc file:

$ gpg -d < abc.enc
gpg: CAST5 encrypted data
gpg: gpg-agent is not available in this session
gpg: encrypted with 1 passphrase
ABC

Each step asks for a passphrase. Symmetric encryption is encryption that can be encrypted and decrypted with the same information, in this case that information is the passphrase.

--force-mdc enables the modification detection code, so that gpg will be able to know if the encrypted text has been modified or not.

Changing your default shell

If you decide that the bash shell is old news and maybe zsh is the real deal you can use the chsh command in ubuntu.

chsh dev -s /usr/bin/zsh

Logout and login for the change to take effect and then check your shell var

$ echo $SHELL
/usr/bin/zsh

Fantastic!

Bracket Ranges

Today while making a bunch of throwaway directories, I tried this command in ZSH:

$ mkdir test_app/{1..5}

This tab-completed to, you guessed it:

$ mkdir test_app/1 test_app/2 test_app/3 test_app/4 test_app/5

Three cheers for laziness! It's useful to know you can use ranges this way (did not work in Bash).

Is that process running? pgrep!

If I want to ask the operating system if a process is running I typically use something like:

$ ps -ax | grep rails

But the output reports two processes, the rails process that is running and the actual grep. Once trick to get past this is:

$ ps -ax | grep [r]ails 

So that the grep looks for a process that starts with r followed by ails but can't find it because the r is followed by ].

But this is an old problem with a fairly old solution. Both mac and linux have a pgrep program.

$ pgrep ruby
44761

Which returns the pid of the process you're looking for. To get more information about the program and its arguments use the -lf flags.

$ pgrep -lf ruby
44761 /Users/devuser/.rvm/rubies/ruby-2.3.1/bin/ruby bin/rails s

See how long a process has been running on #linux

If you started a long-running process and want to know how long it has been on the run so to speak, you can use the -eo switch on ps to specify you want the elapsed time like so:

ps -eo pid,cmd,etime

This will yield something like:

112 [aws/0]                  2-10:27:00
114 [aws/1]                  2-10:27:00
115 [aws/2]                  2-10:27:00
123 [aws/3]                  2-10:27:00
  ...

Which means that process aws has been running for 2 days, 10 hours and 27 minutes.

You can of course pipe the result to grep:

ps -eo pid,cmd,etime | grep aws

Kill Tmux Session From Tmux

If you've ever wrecked a Tmux session (hello, $ cat my-favorite-binary) and needed to kill the session, you don't have to leave Tmux to do so.

We can kill the session right from the Tmux command line ([CTRL + z] is my Tmux prefix):

[CTRL + z] :kill-session

h/t Dorian Karter

List Of Sessions To A Machine

The last command is a handy way to find out who has been connecting to a machine and when.

Last will list the sessions of specified users, ttys, and hosts, in reverse time order. Each line of output contains the user name, the tty from which the session was conducted, any hostname, the start and stop times for the session, and the duration of the session. If the session is still continuing or was cut short by a crash or shutdown, last will so indicate.

In particular, this can be useful for finding an IP address that you want to connect to.

See man last for more details.

iTerm console replay

iTerm 3 (and possibly other versions) lets you rewind/replay the session for that terminal window using ⌘ + Option + b (On a Mac).

Edit the command in your editor

Sometimes when creating a long command at the command line it is easier to edit the command in vim. ctrl+x ctrl+e opens the current command line in your editor.

Open The Current Command In An Editor

If you are working with a complicated command in the terminal trying to get the arguments just right. Such as this curl:

curl https://api.stripe.com/v1/customers \
   -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
   -d description="Customer for test@example.com" \
   -d source=tok_189fCz2eZvKYlo2CsGERUNIW

It can be tedious to move to and modify various parts of the command. However, by hitting Ctrl-x Ctrl-e, the contents of the command buffer will be opened into your default editor (i.e. $EDITOR). This will make editing the command a bit easier. Saving and quitting the editor will put the updated command in the command buffer, ready to run.

Hit Ctrl-x Ctrl-e with an empty command buffer if you want to start crafting a command from scratch or if you are pasting one in from somewhere.

h/t Josh Davey

Heroku Commands By Remote Name

Programming is often a game of inches; a keystroke here, and hotkey there, and suddenly you are doing magical things.

In that spirit, I recently learned that you can run Heroku commands against a remote name (assuming a remote named production):

$ heroku run <command> -rproduction

Instead of like this, which I think is more common:

$ heroku run <command> --app today-i-learned-production

Add those keystrokes to the bank.

Remove a shell function

Say you wrote a function that you don't want anymore:

# ~/.bashrc
function rake() {
  echo 'rake is gone ;)'
}
$ rake db:migrate
rake is gone ;)
$

You can remove it with the unset command:

$ unset -f rake

The -f flag passed to unset ensures that we only remove a function.

Globbing For All Directories In Zsh

Globbing in Zsh is an expressive way to generate filenames for commands. This includes working with directories. If I'd like to run a command against all directories in the current directory, I can employ the *(/) globbing pattern.

$ echo *(/)
one three two

What about all directories in the root directory?

$ echo /*(/)
/Applications /Library /Network /System /Users /Volumes /bin /cores /dev /home /net /opt /private /sbin /usr

You can go ahead and use that with any other command now (e.g. ls).

source

Globbing For Filenames In Zsh

Zsh has extensive support for globbing for filenames. Globbing is a short-hand, of sorts, for generating filenames that meet certain criteria. The generated filenames can be used with any command you might otherwise provide a filename to in a unix setting.

For example, consider a directory full of files including many that are named with numbers. You'd like to list all files that have numeric names.

Doing ls by itself gives the following result:

$ ls
10        11        2         3         4         801       92        code.rb   hello.txt

With the use of a numeric pattern, Zsh's globbing helps ls limit the set of listed files to just those with numeric names:

$ ls *[0-9]
10  11  2   3   4   801 92

This only scrapes the surface of what can be done with globbing in Zsh.

source

h/t Josh Davey

PID Of The Current Shell

$ expands to the process ID of the shell. So, you can see the PID of the current shell with echo $$.

> echo $$
36609

> zsh

> echo $$
45431

> exit

> echo $$
36609

See the Special Paramaters section of man bash for more details.

source

Show Disk Usage For The Current Directory

The du utility can be used to show disk usage for a particular directory or set of directories. When used without any arguments, it will show the disk usage for the current directory.

$ du
80      ./.git/hooks
8       ./.git/info
256     ./.git/logs/refs/heads
...

with the -h command we can see it all in a human-readable format

$ du -h
 40K    ./.git/hooks
4.0K    ./.git/info
128K    ./.git/logs/refs/heads

and to get an even clearer picture we can pipe that through sort -nr

$ du -h | sort -nr
412K    ./vim
352K    ./postgres
340K    ./.git/logs
216K    ./.git/logs/refs
184K    ./ruby
156K    ./unix
148K    ./git
...

This sorts it numerically in reverse order putting the largest stuff at the top.

Sort In Numerical Order

By default, the sort command will sort things alphabetically. If you have numerical input though, you may want a numerical sort. This is what the -n flag is for.

If I have a directory of files with numbered names, sort doesn't quite do the job by itself.

$ ls | sort
1.txt
10.txt
11.txt
12.txt
2.txt
3.txt
4.txt
5.txt

with the -n flag, I get the sort order I am looking for.

$ ls | sort -n
1.txt
2.txt
3.txt
4.txt
5.txt
10.txt
11.txt
12.txt

Highlight code without transient file using pbcopy

I've been creating a LOT of code slides in keynote recently. I'd like to have it highlight and also show up as text rather than a screenshot. And I want it to be EASY!

Look no further. Copy the code snippet you'd like to highlight then run:

pbpaste | highlight -O rtf  --src-lang js --style solarized-dark --font Monaco | pbcopy

This will pass your current paste buffer to highlight, format it, then put it back into your paste buffer for immediate paste into Keynote (or where ever).

Too easy!

Check highlight --help for more options and languages.

highlight brew formula

Exclude A Directory With Find

Using find is a handy way to track down files that meet certain criteria. However, if there are directories full of irrelevant files, you may end up with a lot of noise. What you want to do is exclude or ignore such directories. For example, you probably don't want find to return results from the .git directory of your project.

Specific directories can be excluded by combining the -not and -path arguments.

For instance, to see all files modified within the last 10 days, but not including anything in the .git directory, run the following:

$ find . -type f -not -path './.git/*' -ctime -10

source

SSH Escape Sequences

In Killing A Frozen SSH Session, I talked about an escape sequence for breaking out of an SSH session when the pipe has been broken. This isn't the only SSH escape sequence though. To see the others, hit <Enter>~?. This displays a help list with all the other escape sequences.

> ~?
Supported escape sequences:
 ~.   - terminate connection (and any multiplexed sessions)
 ~B   - send a BREAK to the remote system
 ~C   - open a command line
 ~R   - request rekey
 ~V/v - decrease/increase verbosity (LogLevel)
 ~^Z  - suspend ssh
 ~#   - list forwarded connections
 ~&   - background ssh (when waiting for connections to terminate)
 ~?   - this message
 ~~   - send the escape character by typing it twice
(Note that escapes are only recognized immediately after newline.)

h/t Josh Davey

Pull up the man page for a command while typing

Ever want to read the man page when you are part way through a command line incantation?

Hit <esc>h in zshell and your dreams will come true.

$ tar <esc>h

When you quit the help pager you can pick up right where you left off.

Bypass aliases with the `command` command

If you are writing a bash script to be used by others and you call external dependencies you might encounter a situation where a user has defined an alias in place of the original command.

For example users of the hub command line utillity may have an alias

alias git='hub'

Or something more practically challenging:

alias grep='grep  --color=auto --exclude-dir={.bzr,CVS,.git,.hg,.svn}'

If your command relies on the output of the original program without unexpected modifications you need a way to bypass the aliases and call the command directly.

To bypass aliases prefix the original program call it with the command command. For example:

command git --no-pager diff | command grep '[something]'

I like to think of it as the bash equivalent of Vim's noremap.

Create a directory and cd into it with one command

I don't know about you but I tend to create directories from terminal often, and when I do, cding into them is the first thing I'll do after creating the directory.

This is what it usually looks like

mkdir -p foo/bar/baz
cd foo/bar/baz

This can get quite verbose. You may have also tried this pro tip:

mkdir -p foo/bar/baz
cd !$ # press <TAB> to expand !$ to the last argument of the previous command

But I think this can be even simpler and easier. Add the following to your .zshrc or .bashrc:

mkcd() {
  mkdir -p $1 && cd $1
}

Now source .zshrc/.bashrc and simply run:

mkcd foo/bar/baz

BOOM πŸ’₯

Command Line Length Limitations

The other day I tried to run a rm command on the contents of a directory with a LOT of files.

$ rm images/*

Instead of deleting the contents of the directory, the following message was displayed:

/bin/rm: cannot execute [Argument list too long]

Bash wanted to expand the entire command before executing it. It was too long. But what is too long?

It turns out that we can figure out the max length of commands with the following command:

$ getconf ARG_MAX

For me, the result is 262144.

source 1 and source 2

How would this command be interpreted?

A nice alternative to which is type. They are similar, in that they both indicate how an argument keyword would be interpreted if used as a command name, but the output is different:

$ which ruby
/Users/jwworth/.rvm/rubies/ruby-2.1.0/bin/ruby
$ type ruby
ruby is /Users/jwworth/.rvm/rubies/ruby-2.1.0/bin/ruby

I prefer the type syntax, especially with multiple arguments:

$ type ruby rails bundler
ruby is /Users/jwworth/.rvm/rubies/ruby-2.1.0/bin/ruby
rails is /Users/jwworth/.rvm/gems/ruby-2.1.0/bin/rails
bundler is /Users/jwworth/.rvm/gems/ruby-2.1.0/bin/bundler

Type includes a handy -t flag, which tells you what type of thing the result is:

$ type -t type
builtin
$ type -t ruby
file

See help type (in Bash) for more information.

Enable ScreenSharing from a terminal

At some point you may need VNC access to your remote mac, but you never enabled it. This will let you enable VNC (screen sharing) from a local or SSH connection.

sudo defaults write /var/db/launchd.db/com.apple.launchd/overrides.plist com.apple.screensharing -dict Disabled -bool false
sudo launchctl load /System/Library/LaunchDaemons/com.apple.screensharing.plist

Last Argument Of The Last Command

You can use !$ as a way to reference the last argument in the last command. This makes for an easy shortcut when you want to switch out commands for the same long file name. For instance, if you just ran cat on a file to see its contents

$ cat /Users/jbranchaud/.ssh/config

and now you want to edit that file. You can just pass !$ to the vim command:

$ vim !$

Hit enter or tab to get the full command:

$ vim /Users/jbranchaud/.ssh/config

h/t Dorian Karter

Start Postgres.app from the Command Line

Today I was trying to restore a production Postgres dump on a remote machine, to test some migrations. I haven't granted myself Heroku production database access, hence the SSH into a machine with a Heroku user that has access.

I quickly hit a problemβ€” this remote machine runs Postgres using Postgres.app. Without that program, I'm out of luck. No local Postgres server, no production database restore, no testing.

It turns out you can start Postgres.app from the command line. Find the executable and call it.

jake@remote-machine:$ /Applications/Postgres.app/Contents/MacOS/Postgres

Postgres.app online. I enjoy the image of a remote machine waking up somewhere on a Sunday with a big blue elephant, and 'Welcome to Postgres'.

Homebrew is eating up your harddrive

If you've been using Homebrew on your Mac (if you have a Mac you really should) you may not be aware that every time you upgrade your brew formulas using brew update && brew upgrade Homebrew is leaving behind a copy of the old versions.

With package updates becoming available daily you may end up with gigabytes of space being wasted away on old package versions.

To see how much space the old versions are using run brew cleanup -n. When I ran that command I got:

==> This operation would free approximately 9.2G of disk space.

Holy cannoli! zomg

If you feel like reclaiming that diskspace just run the command again without the -n: brew cleanup.

Enjoy space! πŸš€

Rename The Current tmux Session

If you've created an unnamed tmux session or you no longer like the original name, you can open a prompt to change it by hitting

<prefix>$

Replace the existing name with the desired name and hit enter.

h/t Dorian Karter

Some helpful #unix networking commands

If you are looking to make some connections in your local unix community you should keep in mind a few commands 😜:

Reverse DNS

dig -x xxx.xxx.xxx.xxx

Will allow you to find the hostname for an IP address.

Find IPs and names of computers in your LAN

arp -a

Grep For Files Without A Match

The grep command is generally used to find files whose contents match a pattern. With the -L (--files-without-match) flag, grep can be used to find files that don't match the given pattern.

For instance, to find files in the current directory that don't have foobar anywhere in their content, run:

$ grep -L "foobar" ./*

source

Cat and Splat

Today I learned that cat supports splat (*).

This happened while I was trying to copy a handful of code examples to paste into a Gist, and I ran:

$ cat factor/examples/strings/* | pbcopy

This copied all the files in the strings/ directory into my clipboard, ready to paste into the Gist.

Check if a #ruby gem is installed from bash script

If you are adding customizations to your zshrc, such as adding auto completion for a certain gem, you want to make sure that the gem is installed before performing any action.

The gem list [gemname] -i command returns a boolean representing whether a gem is installed or not.

if `gem list lunchy -i`; then 
  echo "Lunchy gem is installed!"; 
  # do some configuration here
fi

If you wish to be more granular you can check whether a specific version is installed by adding the --version [version] flag.

if `gem list lunchy -i --version 0.10.4`; then 
  echo "Lunchy v0.10.4 is installed!"; 
  # do some configuration here
fi

tar automatically detects file type

For years I have used tar xzf example.tar.gz to decompress tar.gz files and tar xjf example.tar.bz2 to decompress tar.bz2 files. It turns out specifying the compression type (the z or j) is unnecessary. tar can automatically determine the file type. Now I can use tar xf example.tar.gz.

Quickly edit and reload #tmux configuration

When you are playing around with your tmux config you often need to repeatedly open .tmux.conf file and then source it into the current tmux session.

To make things a little faster, add the following to your .tmux.conf:

bind-key r source-file ~/.tmux.conf \; display-message "~/.tmux.conf reloaded"
bind-key M split-window -h "vim ~/.tmux.conf"

Now you can quickly open the tmux config in tmux pane using <prefix> followed by shift + M, edit your configuration, and save when you done. To reload the tmux configuration use <prefix> followed by r.

** <prefix> is C-z for hashrocket's dotfile project (dotmatrix), if you are using tmux default configuration it would be C-b

Fix Tmux 2.1 mode-mouse error

If your tmux started displaying the following error message:

/Users/username/.tmux.conf:136: unknown option: mode-mouse
/Users/username/.tmux.conf:137: unknown option: mouse-select-pane
/Users/username/.tmux.conf:138: unknown option: mouse-resize-pane
/Users/username/.tmux.conf:139: unknown option: mouse-select-window

when you launch it, it is because the tmux 2.1 has a new syntax for turning mouse-mode on. All of the above are now combined into:

set -g mouse on

You'll also notice that after replacing the mouse mode setting with the new one in your config you still cannot scroll up/down with your mouse wheel. To fix that use the following configuration:

bind -n WheelUpPane   select-pane -t= \; copy-mode -e \; send-keys -M
bind -n WheelDownPane select-pane -t= \;                 send-keys -M

Change Default Shell For A User

You can change the default shell program for a particular unix user with the chsh command. Just tell it what shell program you want to use (e.g. bash or zsh) and which user the change is for:

$ [sudo] chsh -s /usr/bin/zsh username

This command needs to be invoked with root privileges.

This command updates the entry for that user in the /etc/passwd file.

source

See the source and location for bash commands

The oh-my-zsh package comes with a lot of useful plugins. Often those plugins add bash functions to the global scope.

If you want to see where the function is defined you can use the type command.

For example the new_gh/exist_gh command which creates a remote repo for a folder

$ type exist_gh
exist_gh is a shell function from /Users/dkarter/.oh-my-zsh/plugins/github/github.plugin.zsh

To see the function source use the declare command:

$ declare -f new_gh
new_gh () {
        cd "$1"
        ghuser=$( git config github.user )
        git init
        print '.*'"\n"'*~' >> .gitignore
        git add ^.*
        git commit -m 'Initial commit.'
        git remote add origin git@github.com:${ghuser}/${repo}.git
        git push -u origin master
}

Verifying Downloads with MD5

Today I downloaded Valgrind and wanted to verify the download's integrity. Valgrind provides an MD5 digest with each release that you can check against.

I used OpenSSL's md5 on OSX:

$ md5 valgrind-3.11.0.tar.bz2
MD5 (valgrind-3.11.0.tar.bz2) = 4ea62074da73ae82e0162d6550d3f129

This matches the digest on the Valgrind website, verifying the download. md5sum would be a comparable Linux program.

After context in Grep

This is my standard grep through a git log:

$ git log | grep 'Extract oauth'
    Extract oauth response parsing

Cool; I found the commit I wanted. However, there is no context here-- I don't know the SHA, date, or committers.

Enter the -a flag, which stands for 'after context'. This flag will add some context to my results.

$ git log | grep 'Extract oauth' -a5 

commit 8e451afl4f292fb86ebbeca8baf5c9578355d3bf
Author: Liz Lemon and Jack Donaghy <dev+lizlemon+jackdonaghy@hashrocket.com>
Date:   Tue Apr 28 10:48:02 2015 -0500

    Extract oauth response parsing

commit a4d16le46ed4286732019c0024db07c85a179210
Author: Liz Lemon and Jack Donaghy <dev+lizlemon+jackdonaghy@hashrocket.com>
Date:   Tue Apr 28 10:17:54 2015 -0500

Now I can git show or git checkout that SHA, or anything else I need to do.

Finding Getters

After writing the other day about why you might not want to use simple getters, I decided that I wanted to eliminate all such methods from a project.

Here is the regex I wrote to isolate the pattern:

ag 'def (\w+);?\s+@\1;?\s+end'

The semicolon catches one-line getter methods as well as the more common three-line.

Try all voices and languages available on OS X say

OS X's say command comes packed with different voices and languages, some of them very entertaining. You can use say to make your scripts more lively.

I wrote a shell script using the say -v? output with the help of vim macros to say the recommended test sentence for each voice sequentially: https://gist.github.com/dkarter/20a2b5fb14f78502249b

Using awk to debug $PATH

If you ever tried printing your system PATH environment variable using echo $PATH you probably got something like this:

/usr/local/heroku/bin:/usr/local/bin:/Users/username/.rvm/gems/ruby-2.2.2/bin:/Users/username/.rvm/gems/ruby-2.2.2@global/bin:/Users/username/.rvm/rubies/ruby-2.2.2/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:.git/safe/../../bin:/Users/username/.bin:/usr/local/sbin:/Users/username/.rvm/gems/ruby-2.2.2/bin:/Users/username/.rvm/gems/ruby-2.2.2@global/bin:/Users/username/.rvm/rubies/ruby-2.2.2/bin:/Users/username/.rvm/bin:/Users/username/.rvm/bin:/Users/username/Dropbox/Developer/gocode/bin

Not a pleasant read.

I thought that would be a good opportunity to practice my awk scripting skills and came up with this:

echo $PATH | awk '{ n = split($0, paths, ":"); for (i=0; ++i <= n;) print i, paths[i] }'

It prints a numerically indexed list of the paths and prints them in separate lines.

1 /usr/local/heroku/bin
2 /usr/local/bin
3 /Users/username/.rvm/gems/ruby-2.2.2/bin
4 /Users/username/.rvm/gems/ruby-2.2.2@global/bi
5 /Users/username/.rvm/rubies/ruby-2.2.2/bin
6 /usr/local/bin
7 /usr/bin
8 /bin
9 /usr/sbin
10 /sbin
11 /opt/X11/bin
12 .git/safe/../../bin
13 /Users/username/.bin
14 /usr/local/sbin
15 /Users/username/.rvm/gems/ruby-2.2.2/bin
16 /Users/username/.rvm/gems/ruby-2.2.2@global/b
17 /Users/username/.rvm/rubies/ruby-2.2.2/bin
18 /Users/username/.rvm/bin
19 /Users/username/.rvm/bin
20 /Users/username/Dropbox/Developer/gocode/bin

You can alias this command if you use it often:

alias print-path=`echo $PATH | awk '{ n = split($0, paths, ":"); for (i=0; ++i <= n;) print i, paths[i] }'`

You may want to check out another rocketeer's (Josh Branchaud) solution to this problem, written in Rust: https://github.com/jbranchaud/ppp

Kill process by name

While killing processes using their PID isn't hard, the process can be simplified further. You can kill a process by its name.

This is how you do it using PID:

ps aux | grep [process_name]
# copy the pid from the output
kill [PID] # paste pid

This is how it's done using the name of the process:

pkill [process_name]
# e.g. pkill rails

Pane Killer

In tmux, the current pane can be killed (closed) using the following key binding:

<prefix>x

You will be prompted to confirm with either y or n.

If there is only one pane in the current window, then the window will be killed along with the pane.

Find (and kill) all processes listening on a port

To search for processes that listen on a specific port use the lsof or List Open Files. The -n argument makes the command run faster by preventing it from doing a ip to hostname conversion. Use grep to show only lines containing the word LISTEN.

lsof -n | grep LISTEN

To filter for a specific port use the following:

lsof -n -i4TCP:[PORT] | grep LISTEN

To kill all processes listening on a specific port use:

lsof -n -i4TCP:[PORT] | grep LISTEN | awk '{ print $2 }' | xargs kill

The awk command returns only the second column (PID), and the xargs executes kill on each line returned.

Add colour to your man pages

Syntax highlighting makes a programmer's life more cheerful. Linux man pages shouldn't be an exception.

Add the following to your zshrc to highlight arguments and commands in man pages:

export LESS_TERMCAP_mb=$(printf '\e[01;31m') # enter blinking mode – red
export LESS_TERMCAP_md=$(printf '\e[01;35m') # enter double-bright mode – bold, magenta
export LESS_TERMCAP_me=$(printf '\e[0m') # turn off all appearance modes (mb, md, so, us)
export LESS_TERMCAP_se=$(printf '\e[0m') # leave standout mode
export LESS_TERMCAP_so=$(printf '\e[01;33m') # enter standout mode – yellow
export LESS_TERMCAP_ue=$(printf '\e[0m') # leave underline mode
export LESS_TERMCAP_us=$(printf '\e[04;36m') # enter underline mode – cyan

Preview

Never leave the home row in bash

To edit a command in bash you often need to jump around in the line and revert to using the arrow keys. As a vim/emacs user this becomes a bit of a clumsy non-ergonomic movement, here are some shortcuts to help you keep your fingers on the home row. If you are an emacs user these are going to look familiar.

  • ctrl-p - previous command entered
  • ctrl-n - next command entered
  • ctrl-a - jump to BOL
  • ctrl-e - jump to EOL
  • alt-b - jump word forward
  • alt-f - jump word backwards
  • alt-b - jump character forward
  • alt-f - jump character backwards

If these shortcuts don't work try running set -o emacs

Alternatively you can turn on vi mode in your shell by calling set -o vi, which you can add to your .zshrc or add set editing-mode vi to your .inputrc. After setting this you can enter normal mode by hitting escape and use vi motions to edit/move.

Your shell just got upgraded. πŸ’ͺπŸ’»

Use `watch` to monitor status commands in bash

If you need to monitor a status command such as monit status or service nginx status, instead of calling the command over and over use the watch command:

watch monit status

by default it will refresh the status every 2 seconds and highlight changes as they occur. You can modify the interval by using the -n switch:

watch -n 1 monit status

If your status command uses color you can turn it on by using the -c switch.

P.S. If you need to run this command on mac you will need to install the watch package using homebrew.

Use bash's Bang command to improve productivity

Bash has neat way to repeat last ran command. In your shell type !! this will put the last ran command in your prompt and allow you to edit and execute it. Use it to add sudo to any command:

$ apt-get install somepackage
Insufficient permissions
$ sudo !!
$ sudo apt-get install somepackage

If you want to go back to a specific command other than the last you have a few options:

You can execute a history command by its ID (to see all IDs run history, to clean history history -c)

$ history
1234 some really long command
1236 third command
$ !1234
$ some really long command
$!-2 # run two commands ago (not including bang commands)
$ history

You can run the last command containing a specific string:

$ foo bar
$ bar foo bazz
$ !foo # last command starting with foo
$ foo bar
$ !?bazz # last command containing the word bazz
$ bar foo bazz

Reuse last/first argument:

$ ls -la /development/reallylongnameidontwanttoretype
$ cd !$
$ cd -la /development/reallylongnameidontwanttoretype
$ $^ app
$ cd app

SSH With A Specific Key

When you SSH into another machine using public key authentication, the key pair from either ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, or ~/.ssh/id_rsa is used by default. This is generally what you want. But what if the target server is expecting to identify you with a different SSH key pair?

The -i option can be used with ssh to specify a different identity file when the default isn't what you want.

Screen Flashing in OSX

I like a quiet computer. But I also like tab-completing commands in the terminal, which produces a necessary alert from time to time.

A solution I found today is to use OSX Accessibility features to add a screen flash on alerts, then disable the sounds.

System Preferences > Accessibility > Hearing menu, choose 'Audio' > Check 'Flash the screen when an alert occurs'

The -A -B and -Cs of Grep

Given the text file things.txt:

foo
bar
baz

When I type cat things.txt | grep 'bar' Then I see just the one line with bar and nothing else, in fact, I have no idea what comes before or after bar.

To know what comes 1 line before bar I can type cat things.txt | grep 'bar' -B 1 then I see:

foo
bar

To know what comes 1 line after bar I can type cat things.txt | grep 'bar' -A 1 then I see:

bar
baz

And to see 1 line either side of the grep result I can type cat things.txt | grep 'bar' -C 1.

File Type Info With File

Use the file utility to determine the type of a file:

$ file todo.md
todo.md: ASCII English text

$ file Hello.java
Hello.java: ASCII C++ program text

$ file Hello.class
Hello.class: compiled Java class data, version 52.0

The Hello.java file isn't exactly a C++ program, but close enough.

Watch That Program

Have you ever been working in the terminal and found yourself repeating the same command many times? Delegate that work to the computer.

watch comes with Linux and can be installed on OSX via homebrew. It executes a program periodically, defaulting to every two seconds.

We used it today while writing a database backup script. Instead of checking our dump directory every time a cron job executed, we ran watch ls, and watched the script succeed or fail with live updates.

man watch for more information.

Printing with lpr

Recently while trying to fix a printer I used lpr a bunch of times. It's not exactly new to me, but never fails to surprise people when I use it.

lpr submits files for printing to your default printer in OSX.

Print a file:

lpr README.md

Print the current file in your Vim session, with a cool job name:

:! lpr -T 'cool job name' %

Print two copies to a specific printer:

lpr -# 2 -P specific_printer README.md

This is an invaluable command-line trick.

Line Kill

Sometimes you completely mess up a command on your terminal and need to start over again. UNIX has a control key for killing a line: control+u

$ ddtae
control + u
$ 
$ date
Mon Sep 26 12:23:39 EDT 1983 

Rerun only failed specs with tmux

You don't want to run your whole sweet again, just those failures?

Copy the bit below Failed examples: into your tmux buffer:

rspec ./spec/mailers/order_mailer_spec.rb:5 # OrderMailer reciept includes the support email and phone number
rspec ./spec/features/customer_checks_out_spec.rb:43 # customer checks out happy path
...

Now make command line args for rspec out of it:

tmux showb | ag -o '[^\s]+:\d+' | tr '\n' ' ' > rerun.txt

Run only this set of specs with xargs:

xargs rspec < rerun.txt

Referencing jobs (to kill them)

Generally I've killed processes by pid, like kill -9 30452, but that involves looking up the pid. If your shell started the job you can reference the process by its job id %number.

> cat &
[1] 70058
[1]  + suspended (tty input)  cat
> kill %1
[1]  + terminated  cat

Or you can reference it by name %name

> cat &
[1] 70064
[1]  + suspended (tty input)  cat
> kill %cat
[1]  + terminated  cat

Killing processes in this way surprisingly only works on the last started job.

> cat & ; cat &
[1] 70110
[2] 70111
[2]  + suspended (tty input)  cat
[1]  + suspended (tty input)  cat
> kill %cat
[2]  - terminated  cat
> jobs -l
[1]  + 70110 suspended (tty input)  cat

Moving forth and back on command line

Whenever I use bindkey to list the command line key bindings I see entries such as

"^[f" forward-word
"^[b" backward-word

Alt-f and Alt-b. But when I try to use those I get characters such as Ζ’ and ∫.

To use forward and backward word in iTerm you must edit a profile in the iTerm preferences and choose the option 'Left Option acts as +Esc' and 'Right Option acts as +Esc'.

Securely Remove Files

If you really want to make sure you have wiped a file from your hard drive, you are going to want to use srm instead of rm. The man page for srm gives the following description:

srm removes each specified file by overwriting, renaming, and truncating it before unlinking. This prevents other people from undeleting or recovering any information about the file from the command line.

h/t Dillon Hafer

Global Substitution On The Previous Command

Let's say we just executed the following command:

$ grep 'foo' foo.md

It gave us the information we were looking for and now we want to execute a similar command to find the occurrences of bar in bar.md. The ^ trick won't quite work here.

$ ^foo^bar<tab>
$ grep 'bar' foo.md

What we need is a global replace of foo in our previous command. The !! command can help when we sprinkle in some sed-like syntax.

$ !!gs/foo/bar<tab>
$ grep 'bar' bar.md

For a short command like this, we haven't gained much. However, for large commands that span the length of the terminal, this can definitely save us a little trouble.

Do Not Overwrite Existing Files

When using the cp command to copy files, you can use the -n flag to make sure that you do not overwrite existing files.

h/t Dillon Hafer

Change Owners and Groups Together

We can change the owner and group for a file or directory with this command:

$ sudo chown dev:dev test.txt

Now, the owner and group of 'test.txt' will be the 'dev' user and 'dev' group, respectively.

h/t Jack Christensen

source

List All The Say Voices

The say command can be a fun party trick.

$ say Get ready for the bass to drop

Your friends will be even more impressed when you use some of the alternate voices.

$ say -v Daniel Would you like a cup of tea?

To see all the alternate voices available, type the following

$ say -v '?'

source

Cycle Through tmux Layouts

Arranging a series of split windows in tmux can take some time. Once those splits windows are arranged, it is difficult to set them up in a new way. There is a way of cycling through layouts that might be able to help though. Hit <prefix><space> over and over to cycle through the layouts until you find the arrangement that you want.

source

Create A Named tmux Session

When creating a new tmux session

$ tmux new

a default name of 0 will be given to the session.

If you'd like to give your session a name with a bit more meaning, use the -s flag

$ tmux new -s burrito

source

Create with Timestamp

Today I learned how to interpolate a timestamp at the command line. Here are two examples:

For a file:

$ touch test_$(date +%s).md
$ ls
test_1435435401.md

For a git branch:

$ git checkout -b pull_request_$(date +%s)
Switched to a new branch 'pull_request_1435435344'

The timestamp represents seconds since the UNIX epoch.

Repeat Yourself

Use the repeat command to repeat some other command.

You can repeat a command any number of times like so

$ repeat 5 say Hello World

Watch The Difference

The watch command is a simple way to repeatedly run a particular command. I'll sometimes use it to monitor the response from some endpoint. watch can make monitoring responses even easier when the -d flag is employed. This flag instructs watch to highlight the parts of the output that are different from the previous run of the command.

So if I run

$ watch -d curl -LIs localhost:3000

I can easily see if the http status of the request changes.

Check If A Port Is In Use

The lsof command is used to list open files. This includes listing network connections. This means I can check if a particular port is in use and what process is using that port. For instance, I can check if my rails application is currently running on port 3000.

$ lsof -i TCP:3000
COMMAND   PID       USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ruby    13821 jbranchaud   12u  IPv6 0xdf2e9fd346cc12b5      0t0  TCP localhost:hbci (LISTEN)
ruby    13821 jbranchaud   13u  IPv4 0xdf2e9fd33ca74d65      0t0  TCP localhost:hbci (LISTEN)

I can see that a ruby process (my rails app) is using port 3000. The PID and a number of other details are included.

See more details with man lsof.

h/t Mike Chau

List All tmux Key Bindings

There are a couple ways to list all the tmux key bindings. If you are not currently in a tmux session, you can still access the list from the terminal with

$ tmux list-keys

If you are currently in a tmux session, then you can take advantage of the tmux environment by either using

<prefix>:list-keys

or

<prefix>?

Any of these will bring up a list of all key bindings available to you within a tmux session on your machine.

Replace ERB files with HAML

The gem htmltohaml provides an easy method to convert your ERB files into HAML files. It generates a new converted file with the .haml extension for each .erb file, leaving you with both copies.

Today I used this command to quickly remove about twenty of these redundant .erb files, after adding the .haml files.

$ find . -name \*.erb | xargs git rm

Moving / Copying with Curly Braces

This might be old news, but it's relatively new to me, so here: you can move/copy files using curly braces; the text before the comma is replaced with the text after, so instead of this:

$ mv awesome/explosion.gif rad/explosion.gif

Do this:

$ mv {awesome,rad}/explosion.gif

Works great for any subset of the argument (even partial file/folder names).

Saying Yes

Tired of being prompted for confirmation by command-line utilities? Wish you could blindly respond 'yes' to whatever it is they are bugging you about? The yes command is what you've been looking for.

$ yes | rm -r ~/some/dir

This will respond y as rm asks for confirmation on removing each and every file in that directory.

yes is just as good at saying no. Give it no as an argument and it will happily (and endlessly) print no.

$ yes no

h/t Chris Erin

Reclaiming The Entire Window in tmux

If you have attached to a tmux session whose dimensions are being constrained by another connection, you may find an L-shaped portion of your window filled with dots. tmux defers to the session with smaller dimensions. The easiest way to reclaim the entire window for your session is to attach to the session while forcing all other sessions to detach. The -d flag will help with that.

$ tmux attach-session -d -t my-session

By detaching all other sessions, you are ensuring that your machine's dimensions are the ones that tmux uses when drawing the window. This is a great quick fix if you're working on your own, but probably not what you want to do if you are in a pair programming situation.

source

Switch Version of a Brew Formula

If you've installed a couple versions of a program via brew and you'd like to switch from the currently linked version to the other installed version, you can use the switch command. For instance, if you are on version 1.8.2 of phantomjs and you'd like to switch to 1.9.0, you can simply invoke:

$ brew switch phantomjs 1.9.0

More generically:

$ brew switch <formula> <version>

Organizing tmux windows

If you use a number of tmux windows as part of your daily workflow, you may find that they get to be a bit of a mess from time to time. There are gaps in the numbering and they aren't laid out in the order you'd prefer. The movew command makes it easy to rearrange these windows.

If you have a window indexed at 2 and you want it to be the 4th window, then you can:

:movew -s 2 -t 4

If you have a gap such that the 4th and 5th windows are numbered 4 and 7, then you can focus the 7 window and simply invoke:

:movew

And that window will be reinserted at the next available slot, in this case, window 5.

MD5 File Signatures

The command md5 <file> generates a unique 32-digit hexadecimal number. This can serve as a signature for a file in its particular state, letting you know when it has changed.

Example usage:

$ touch test.txt
$ md5 test.txt
  MD5 (test.txt) = d41d8cd98f00b204e9800998ecf8427e
$ echo 'some content' > test.txt
$ md5 test.txt
  MD5 (test.txt) = eb9c2bf0eb63f3a7bc0ea37ef18aeba5

Directional Commands

You can move the cursor without arrow keys. Here is the keyboard equivalent for each.

  • Up ('previous'): CTRL + P
  • Down ('next'): CTRL + N
  • Left ('back'): CTRL + B
  • Right ('forward'): CTRL + F

Mapping caps lock to CTRL makes these combinations very accessible.

Bird Beak Bash (or process substitution)

http://www.tldp.org/LDP/abs/html/process-sub.html

Process substitution feeds the output of a process (or processes) into the stdin of another process.

<() creates a file descriptor and is most useful when using a command that takes two files as arguments like diff or comm but you want to use output from commands rather than files.

comm <(ls dirA) <(ls dirB)

mkdir -p throws no errors

mkdir throws errors if you try to create a directory that already exists.

mkdir -p is cool with not creating and not throwing an error if you try to create a dir that already exists.

From the man page:

On the other hand, with this option specified, no error will be reported if a directory given as an operand already exists.

That feels a lot better than if [ ! -f myDir ]; then mkdir myDir end; fi

All The Environment Variables

If you want to see all the environment variables defined on your machine, you can list them all out with printenv. If you are like me, you probably have a ton of them. Pipe it through less to make it easier to navigate and search through (i.e. printenv | less).

Cat A File With Line Numbers

You can quickly view a file using cat

$ cat Gemfile
source 'https://rubygems.org'


# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.0'
# Use postgresql as the database for Active Record
gem 'pg'

With the -n flag you can view that file with line numbers

$ cat -n Gemfile
 1  source 'https://rubygems.org'
 2  
 3  
 4  # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
 5  gem 'rails', '4.2.0'
 6  # Use postgresql as the database for Active Record
 7  gem 'pg'

Docker volume binding

When starting a docker dir, you can map a dir on the host system to a dir in the container with the -v option.

docker start my-image -v /var/logs/app:/app/log

In this case the host dir is on the left side of the colon and the docker container dir is on the right.

*nix user ids and groups

Does a user exist on the system?

$ id -u <username>

That'll give you the id, like 1006.

$ groups <username>

That'll give you the groups a user is a member of, like ssh staff admin

tmux in your tmux

If you are running tmux locally and you shell into another machine to access tmux remotely, you will suddenly find yourself in tmux inception. You will have a tmux instance running within your local tmux instance. If you have the same prefix key set for both, then you may be wondering how you can send a tmux command to the inner tmux instance.

If you press your prefix twice (e.g. <C-a> <C-a>), then the second prefix will be sent to the inner tmux instance which will then be listening for the rest of your command. So, to open a new window within the inner tmux instance, you can hit <C-a> <C-a> c.

Tmux command targets

With a new commit to our environment to enable project specific tmux configurations its been fun to dig into tmux automation.

tmux send-keys -t seq27:0.0 'vim .' C-m

Will send the keys 'vim .' to a very specific target -t seq27:0.0

seq27 = the name of the session

0 = the first window of that session

0 = the first pane of that window

Thats how you can open vim in a specific pane in your tmux session automatically!

Bash true!

We needed to inspect that a return code made it back from docker's exec command today.

  docker exec -it <docker-container> "true" && echo "TRUE"

Will print TRUE

  docker exec -it <docker-container> "! true" && echo "WONT GET PRINTED"

Won't print anything! Return codes FTW. true returns 0. ! true returns 1.

Create A File Descriptor With Process Substitution

Process substitution can be used to create a file descriptor from the evaluation of a shell command. The syntax for process substitution is <(LIST) where LIST is one or more bash commands.

$ cat <(echo 'hello, world')
hello, world

This is particularly useful for commands that expect files, such as diff:

$ diff <(echo 'hello, world') <(echo 'hello, mars')
1c1
< hello, world
---
> hello, mars

Sources: Brian Dunn and Bash Guide for Beginners

Ignore hang ups when starting a process

Start a process, exit the current shell, process continues.

$ nohup rake qc:work &

nohup enables your program to ignore the HUP signal a controlling process sends.

Example

$ nohup cat &                                                                                                              
> [1] 2766
> appending output to nohup.out
$ kill -1 2766
$ ps -A | grep 2766
> 2766 ttys003    0:00.00 cat

less help

While in less (terminal pager program), h or H brings up a summary of commands.

Standard output to clipboard buffer

Adding | pbcopy to the end of any command will send the standard output to your clipboard.

ls -al | pbcopy inside a rails project directory allowed me to paste this:

Gemfile
Gemfile.lock
README.md
Rakefile
app
bin
config
config.ru
db
features
lib
log
public
script
spec
test
tmp
vendor