Code for Concinnity

beautiful and elegant solutions


Some great bash command line tricks I learned lately

Many adopted from Peteris Krumins’ blog post

Display mounted file systems nicely

The main point here is really about the column command:

1
2
3
4
5
6
7
8
9
10
11
$ mount
/dev/root on / type ext3 (rw)
/proc on /proc type proc (rw)
/dev/mapper/lvmraid-home on /home type ext3 (rw,noatime)

$ mount | column -t
/dev/root                 on  /      type  ext3   (rw)
/proc                     on  /proc  type  proc   (rw)
/dev/mapper/lvmraid-home  on  /home  type  ext3   (rw,noatime)

# woot, now it's printing out nicely!

Repeat arguments of the most recent command

Alt + .

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
$ echo hello world
hello world

$ echo (Alt + .) # this becomes...
$ echo world

# Cool, but what if I wanted "hello"?

$ echo hello world
hello world

$ echo (Alt + 1)(Alt + .)
$ echo hello # here you go!

# Doing the same thing with history expansion
$ echo hello world
$ echo !!:1
echo hello
hello

# There's a shorthand for the last argument in history expansion
$ echo hello world
$ echo !$
echo world
world

Edit the whole command line in $EDITOR

This one is extremely huge. Ever got tired of doing those multiple lines long ffmpeg command lines? Here’s your salvation (and his name is vi)

1
2
$ ffmpeg -i my-input-file.avi <Ctrl+x><Ctrl+e>
# You can specify multiple command lines in your $EDITOR and they'll be executed one by one, cool!
Published by kizzx2, on April 22nd, 2010 at 2:34 am. Filled under: Interesting things Tags: , , No Comments

Iterating Bash arrays with spaces

The problem

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
#!/bin/sh

$ a=(hello world foo bar)
$ for i in #{a[*]}; do echo $i; done

# Expected output:
#   hello
#   world
#   foo
#   bar

# so far so good:
#   hello
#   world
#   foo
#   bar

$ a=("hello world" "foo bar")
$ for i in #{a[*]}; do echo $i; done

# Expected output:
#   hello world
#   foo bar

# omg:
#   hello
#   world
#   foo
#   bar

The problem is caused by the affect that Bash uses space as array element separator internally.

Failed attempt

1
2
3
4
5
6
7
8
9
10
11
#!/bin/sh

$ a=("hello world" "foo bar")
$ for i in "#{a[*]}"; do echo $i; done

# Expected output:
#   hello world
#   foo bar

# zomg!
#   hello world foo bar

The solution

The solution lies in the magical $@ expansion. When the $@ expansion is put in a quote, the shell automatically expands each element properly quoted:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/sh

a=("hello world" "foo bar")
for i in "#{a[@]}"; do echo $i; done

# Expected output:
#   hello world
#   foo bar

# yay!
#   hello world
#   foo bar
Published by kizzx2, on April 10th, 2010 at 1:27 am. Filled under: Useful tips Tags: , , , No Comments