Bash: Difference between revisions
From charlesreid1
No edit summary |
No edit summary |
||
| (9 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
Bash Quick Reference: [[Bash/Quick]] | |||
Bash Quick Prototype: [[Bash/Prototype]] | |||
= Bash Guide = | = Bash Guide = | ||
| Line 5: | Line 9: | ||
Setting the default shell: http://www.unix.com/shell-programming-scripting/32664-how-change-default-shell-linux.html | Setting the default shell: http://www.unix.com/shell-programming-scripting/32664-how-change-default-shell-linux.html | ||
[[Image:OSXTerminalSettings.png|none|250px|frame|You can set the default shell in Mac's Terminal by going | [[Image:OSXTerminalSettings.png|none|250px|frame|You can set the default shell in Mac's Terminal by going to <code>Terminal > Preferences</code> and specifying the login shell.]] | ||
== Startup Process == | == Startup Process == | ||
{{Main|Dot files}} | |||
== Dot Files == | |||
= Bash Scripting = | |||
== Looping == | |||
Looping in bash is really simple, and convenient - you can use other unix commands (most obviously "ls") to create lists, and then loop over each element of those lists. For example, if I want to print out the name of every file in my home directory (granted, not very useful, but this is just an example), I can do this: | |||
<pre> | |||
for i in `/bin/ls -1 $HOME`; do | |||
echo $i | |||
done | |||
</pre> | |||
To do some serious bash looping kung-fu, check out [[Xargs]]. | |||
==Bash Loop One-Liner: Seq and Destroy== | |||
Sometimes, you want to do a bash loop, but you want to do it on the fly, so you don't have to fire up your text editor and make a bash script. | |||
[[Seq]] to the rescue! | |||
The seq command is a way of creating very simple numerical sequences: | |||
<pre> | |||
$ seq 1 10 | |||
1 | |||
2 | |||
3 | |||
4 | |||
5 | |||
6 | |||
7 | |||
8 | |||
9 | |||
10 | |||
</pre> | |||
But seq has some other features that make it very handy (see the [[Seq]] page for a full list of examples). | |||
Seq can be very easily combined with bash to create one-line for loops. | |||
Let's pose a simple scenario: say you've imported a bunch of photos from your camera, and their naming convention looks like this:got a lit of photos like this: | |||
{{Scroll box | |||
|content= | |||
<pre> | |||
IMG_0000.jpg | |||
IMG_0001.jpg | |||
IMG_0002.jpg | |||
IMG_0003.jpg | |||
IMG_0004.jpg | |||
IMG_0005.jpg | |||
IMG_0006.jpg | |||
IMG_0007.jpg | |||
IMG_0008.jpg | |||
IMG_0009.jpg | |||
IMG_0010.jpg | |||
IMG_0011.jpg | |||
IMG_0012.jpg | |||
IMG_0013.jpg | |||
IMG_0014.jpg | |||
IMG_0015.jpg | |||
IMG_0016.jpg | |||
IMG_0017.jpg | |||
IMG_0018.jpg | |||
IMG_0019.jpg | |||
IMG_0020.jpg | |||
IMG_0021.jpg | |||
IMG_0022.jpg | |||
IMG_0023.jpg | |||
IMG_0024.jpg | |||
IMG_0025.jpg | |||
IMG_0026.jpg | |||
IMG_0027.jpg | |||
IMG_0028.jpg | |||
IMG_0029.jpg | |||
IMG_0030.jpg | |||
IMG_0031.jpg | |||
IMG_0032.jpg | |||
IMG_0033.jpg | |||
IMG_0034.jpg | |||
IMG_0035.jpg | |||
IMG_0036.jpg | |||
IMG_0037.jpg | |||
IMG_0038.jpg | |||
IMG_0039.jpg | |||
IMG_0040.jpg | |||
IMG_0041.jpg | |||
IMG_0042.jpg | |||
IMG_0043.jpg | |||
IMG_0044.jpg | |||
IMG_0045.jpg | |||
IMG_0046.jpg | |||
IMG_0047.jpg | |||
IMG_0048.jpg | |||
IMG_0049.jpg | |||
IMG_0050.jpg | |||
</pre> | |||
}} | |||
Now, let's say we want to move some photos to another folder, but we only want to move the odd-numbered photographs starting at 10 and ending at 40. | |||
We can whip up a quick seq command that'll give us even numbers from 10 to 40: | |||
<pre> | |||
$ seq 10 2 40 | |||
</pre> | |||
But we need the whole thing to be formatted into a comma-separated list, so we can feed it to a bash command, like <code>mv {this,that} the_other/.</code>. So let's use the -s flag: | |||
<pre> | |||
$ seq -s, 10 2 40 | |||
10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40, | |||
</pre> | |||
Now we can use bash's backticks to plop that command in the middle of another mv command: | |||
<pre> | |||
$ mv directory1/IMG_00{`seq -s, 10 2 40`}.jpg directory2/. | |||
</pre> | |||
which unfolds to: | |||
{{Scroll box | |||
|content= | |||
<pre> | |||
mv directory1/IMG_0010.jpg directory2/. | |||
mv directory1/IMG_0012.jpg directory2/. | |||
mv directory1/IMG_0014.jpg directory2/. | |||
mv directory1/IMG_0016.jpg directory2/. | |||
mv directory1/IMG_0018.jpg directory2/. | |||
mv directory1/IMG_0020.jpg directory2/. | |||
mv directory1/IMG_0022.jpg directory2/. | |||
mv directory1/IMG_0024.jpg directory2/. | |||
mv directory1/IMG_0026.jpg directory2/. | |||
mv directory1/IMG_0028.jpg directory2/. | |||
mv directory1/IMG_0030.jpg directory2/. | |||
mv directory1/IMG_0032.jpg directory2/. | |||
mv directory1/IMG_0034.jpg directory2/. | |||
mv directory1/IMG_0036.jpg directory2/. | |||
mv directory1/IMG_0038.jpg directory2/. | |||
mv directory1/IMG_0040.jpg directory2/. | |||
</pre> | |||
}} | |||
Voila! | |||
But what if the range of file numbers strides 100? If you wanted to go from 80 to 120, you would end up with mismatching zero-padding. To get around this, you could either force seq to output all numbers with a fixed width (using the -w flag), or you could get more fancy by specifying a printf (print format) string for seq to use when printing each number (via the -f flag in seq). | |||
Let's repeat the example, but this time using the printf approach. First, we want to print a 4-digit number that is zero-padded, meaning our printf string is going to be <code>%04g</code>. Now the seq command looks like: | |||
<pre> | |||
$ seq -s, -f'%04g' 80 2 120 | |||
0080,0082,0084,0086,0088,0090,0092,0094,0096,0098,0100,0102,0104,0106,0108,0110,0112,0114,0116,0118,0120, | |||
</pre> | |||
(Note we could have also used the printf string <code>'IMG_%04g.jpg'</code> to make things a little more compact.) | |||
Now we can feed that directly to the mv command: | |||
<pre> | |||
$ mv directory1/IMG_{`seq -s, -f'%04g' 80 2 120`}.jpg directory2/. | |||
</pre> | |||
which unfolds into the set of bash commands: | |||
{{Scroll box | |||
|content= | |||
<pre> | |||
mv directory1/IMG_0080.jpg directory2/. | |||
mv directory1/IMG_0082.jpg directory2/. | |||
mv directory1/IMG_0084.jpg directory2/. | |||
mv directory1/IMG_0086.jpg directory2/. | |||
mv directory1/IMG_0088.jpg directory2/. | |||
mv directory1/IMG_0090.jpg directory2/. | |||
mv directory1/IMG_0092.jpg directory2/. | |||
mv directory1/IMG_0094.jpg directory2/. | |||
mv directory1/IMG_0096.jpg directory2/. | |||
mv directory1/IMG_0098.jpg directory2/. | |||
mv directory1/IMG_0100.jpg directory2/. | |||
mv directory1/IMG_0102.jpg directory2/. | |||
mv directory1/IMG_0104.jpg directory2/. | |||
mv directory1/IMG_0106.jpg directory2/. | |||
mv directory1/IMG_0108.jpg directory2/. | |||
mv directory1/IMG_0110.jpg directory2/. | |||
mv directory1/IMG_0112.jpg directory2/. | |||
mv directory1/IMG_0114.jpg directory2/. | |||
mv directory1/IMG_0116.jpg directory2/. | |||
mv directory1/IMG_0118.jpg directory2/. | |||
mv directory1/IMG_0120.jpg directory2/. | |||
</pre> | |||
}} | |||
Voila! | |||
You can find more information about seq, and how to couple it with other Unix utilities, at the [[Seq]] page on my wiki. | |||
== Logical Operators == | == Logical Operators == | ||
| Line 55: | Line 223: | ||
These can be tested using a simple "if" statement. In bash, if statements are of the form: | These can be tested using a simple "if" statement. In bash, if statements are of the form: | ||
< | <pre> | ||
if [[ condition ]]; then | if [[ condition ]]; then | ||
cmd | cmd | ||
| Line 61: | Line 229: | ||
cmd2 | cmd2 | ||
fi | fi | ||
</ | </pre> | ||
The spaces between the brackets and the condition are essential. | The spaces between the brackets and the condition are essential. | ||
A comprehensive list of logical condition checks is here: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html | |||
===Integer Operators=== | ===Integer Operators=== | ||
| Line 75: | Line 245: | ||
|<code>-eq</code> | |<code>-eq</code> | ||
|returns true if arguments are equal | |returns true if arguments are equal | ||
|< | |<pre> | ||
$ a=1; b=1; if [[ "$a" -eq "$b" ]]; then echo "true"; else echo "false"; fi | $ a=1; b=1; if [[ "$a" -eq "$b" ]]; then echo "true"; else echo "false"; fi | ||
true | true | ||
| Line 81: | Line 251: | ||
$ a=1; b=2; if [[ "$a" -eq "$b" ]]; then echo "true"; else echo "false"; fi | $ a=1; b=2; if [[ "$a" -eq "$b" ]]; then echo "true"; else echo "false"; fi | ||
false | false | ||
</ | </pre> | ||
|- | |- | ||
|<code>-ne</code> | |<code>-ne</code> | ||
|returns true if arguments are not equal | |returns true if arguments are not equal | ||
|< | |<pre> | ||
$ a=1; b=1; if [[ "$a" -ne "$b" ]]; then echo "true"; else echo "false"; fi | $ a=1; b=1; if [[ "$a" -ne "$b" ]]; then echo "true"; else echo "false"; fi | ||
false | false | ||
| Line 92: | Line 262: | ||
$ a=1; b=2; if [[ "$a" -ne "$b" ]]; then echo "true"; else echo "false"; fi | $ a=1; b=2; if [[ "$a" -ne "$b" ]]; then echo "true"; else echo "false"; fi | ||
true | true | ||
</ | </pre> | ||
|- | |- | ||
|<code>-gt</code> | |<code>-gt</code> | ||
|returns true if argument 1 is greater than argument 2 | |returns true if argument 1 is greater than argument 2 | ||
|< | |<pre> | ||
$ a=5; b=10; if [[ "$a" -gt "$b" ]]; then echo "true"; else echo "false"; fi | $ a=5; b=10; if [[ "$a" -gt "$b" ]]; then echo "true"; else echo "false"; fi | ||
false | false | ||
</ | </pre> | ||
|- | |- | ||
|<code>-ge</code> | |<code>-ge</code> | ||
|returns true if argument 1 is greater than or equal to argument 2 | |returns true if argument 1 is greater than or equal to argument 2 | ||
|< | |<pre> | ||
$ a=15; b=10; if [[ "$a" -ge "$b" ]]; then echo "true"; else echo "false"; fi | $ a=15; b=10; if [[ "$a" -ge "$b" ]]; then echo "true"; else echo "false"; fi | ||
true | true | ||
| Line 111: | Line 281: | ||
$ a=10; b=10; if [[ "$a" -ge "$b" ]]; then echo "true"; else echo "false"; fi | $ a=10; b=10; if [[ "$a" -ge "$b" ]]; then echo "true"; else echo "false"; fi | ||
true | true | ||
</ | </pre> | ||
|- | |- | ||
|<code>-lt</code> | |<code>-lt</code> | ||
|returns true if argument 1 less than argument 2 | |returns true if argument 1 less than argument 2 | ||
|< | |<pre> | ||
$ a=5; b=10; if [[ "$a" -lt "$b" ]]; then echo "true"; else echo "false"; fi | $ a=5; b=10; if [[ "$a" -lt "$b" ]]; then echo "true"; else echo "false"; fi | ||
true | true | ||
</ | </pre> | ||
|- | |- | ||
|<code>-le</code> | |<code>-le</code> | ||
|returns true if argument 1 less than or equal to argument 2 | |returns true if argument 1 less than or equal to argument 2 | ||
|< | |<pre> | ||
$ a=15; b=10; if [[ "$a" -le "$b" ]]; then echo "true"; else echo "false"; fi | $ a=15; b=10; if [[ "$a" -le "$b" ]]; then echo "true"; else echo "false"; fi | ||
false | false | ||
| Line 130: | Line 300: | ||
$ a=10; b=10; if [[ "$a" -le "$b" ]]; then echo "true"; else echo "false"; fi | $ a=10; b=10; if [[ "$a" -le "$b" ]]; then echo "true"; else echo "false"; fi | ||
true | true | ||
</ | </pre> | ||
|- | |- | ||
| Line 137: | Line 307: | ||
this needs to be escaped with a \ if it occurs inside single brackets; otherwise it can appear between double bracket or between double parentheses | this needs to be escaped with a \ if it occurs inside single brackets; otherwise it can appear between double bracket or between double parentheses | ||
|< | |<pre> | ||
$ a=10; b=10; if [ "$a" \< "$b" ]; then echo "true"; else echo "false"; fi | $ a=10; b=10; if [ "$a" \< "$b" ]; then echo "true"; else echo "false"; fi | ||
false | false | ||
| Line 146: | Line 316: | ||
$ a=10; b=10; if (( "$a" < "$b" )); then echo "true"; else echo "false"; fi | $ a=10; b=10; if (( "$a" < "$b" )); then echo "true"; else echo "false"; fi | ||
false | false | ||
</ | </pre> | ||
|- | |- | ||
| Line 153: | Line 323: | ||
this operator needs to go inside double parentheses | this operator needs to go inside double parentheses | ||
|< | |<pre> | ||
$ a=10; b=10; if (( "$a" <= "$b" )); then echo "true"; else echo "false"; fi | $ a=10; b=10; if (( "$a" <= "$b" )); then echo "true"; else echo "false"; fi | ||
true | true | ||
</ | </pre> | ||
|- | |- | ||
| Line 163: | Line 333: | ||
this needs to be escaped with a \ if it occurs inside single brackets; otherwise it can appear between double bracket or between double parentheses | this needs to be escaped with a \ if it occurs inside single brackets; otherwise it can appear between double bracket or between double parentheses | ||
|< | |<pre> | ||
$ z=10; zz=1000; | $ z=10; zz=1000; | ||
| Line 171: | Line 341: | ||
$ if [[ zz > z ]]; then echo "true"; else echo "false"; fi | $ if [[ zz > z ]]; then echo "true"; else echo "false"; fi | ||
true | true | ||
</ | </pre> | ||
|- | |- | ||
| Line 178: | Line 348: | ||
this operator needs to go inside double parentheses | this operator needs to go inside double parentheses | ||
|< | |<pre> | ||
$ a=50; b=10; if (( $a >= $b )); then echo "true"; else echo "false"; fi | $ a=50; b=10; if (( $a >= $b )); then echo "true"; else echo "false"; fi | ||
true | true | ||
</ | </pre> | ||
|} | |} | ||
| Line 195: | Line 365: | ||
|<code>=</code> | |<code>=</code> | ||
|returns true if two strings are equal | |returns true if two strings are equal | ||
|< | |<pre> | ||
$ a=foo; b=foo; if [[ "$a" = "$b" ]]; then echo "true"; else echo "false"; fi | $ a=foo; b=foo; if [[ "$a" = "$b" ]]; then echo "true"; else echo "false"; fi | ||
true | true | ||
| Line 201: | Line 371: | ||
$ a=foo; b=bar; if [[ "$a" = "$b" ]]; then echo "true"; else echo "false"; fi | $ a=foo; b=bar; if [[ "$a" = "$b" ]]; then echo "true"; else echo "false"; fi | ||
false | false | ||
</ | </pre> | ||
|- | |- | ||
|<code>==</code> | |<code>==</code> | ||
|returns true if two strings are equal; equivalent to <code>=</code> | |returns true if two strings are equal; equivalent to <code>=</code> | ||
|< | |<pre> | ||
$ a=foo; b=foo; if [[ "$a" == "$b" ]]; then echo "true"; else echo "false"; fi | $ a=foo; b=foo; if [[ "$a" == "$b" ]]; then echo "true"; else echo "false"; fi | ||
true | true | ||
| Line 212: | Line 382: | ||
$ a=foo; b=bar; if [[ "$a" == "$b" ]]; then echo "true"; else echo "false"; fi | $ a=foo; b=bar; if [[ "$a" == "$b" ]]; then echo "true"; else echo "false"; fi | ||
false | false | ||
</ | </pre> | ||
Note the difference between quoting a string and not quoting a string: | Note the difference between quoting a string and not quoting a string: | ||
| Line 224: | Line 394: | ||
|<code>!=</code> | |<code>!=</code> | ||
|returns true if strings are not equal | |returns true if strings are not equal | ||
|< | |<pre> | ||
$ a=foo; b=bar; if [[ "$a" != "$b" ]]; then echo "true"; else echo "false"; fi | $ a=foo; b=bar; if [[ "$a" != "$b" ]]; then echo "true"; else echo "false"; fi | ||
true | true | ||
</ | </pre> | ||
|- | |- | ||
|<code> < </code> | |<code> < </code> | ||
|returns true if argument 1 is less than (alphabetically) argument 2; capitals come before non-capitals | |returns true if argument 1 is less than (alphabetically) argument 2; capitals come before non-capitals | ||
|< | |<pre> | ||
$ a=foo; b=bar; if [[ "$a" < "$b" ]]; then echo "true"; else echo "false"; fi | $ a=foo; b=bar; if [[ "$a" < "$b" ]]; then echo "true"; else echo "false"; fi | ||
false | false | ||
| Line 241: | Line 411: | ||
$ a=bar; b=foo; if [[ "$a" < "$b" ]]; then echo "true"; else echo "false"; fi | $ a=bar; b=foo; if [[ "$a" < "$b" ]]; then echo "true"; else echo "false"; fi | ||
true | true | ||
</ | </pre> | ||
|- | |- | ||
|<code> > </code> | |<code> > </code> | ||
|returns true if argument 1 is greater than (alphabetically) argument 2; capitals come before non-capitals | |returns true if argument 1 is greater than (alphabetically) argument 2; capitals come before non-capitals | ||
|< | |<pre> | ||
$ a=foo; b=bar; if [[ "$a" > "$b" ]]; then echo "true"; else echo "false"; fi | $ a=foo; b=bar; if [[ "$a" > "$b" ]]; then echo "true"; else echo "false"; fi | ||
true | true | ||
| Line 252: | Line 422: | ||
$ a=Foo; b=bar; if [[ "$a" > "$b" ]]; then echo "true"; else echo "false"; fi | $ a=Foo; b=bar; if [[ "$a" > "$b" ]]; then echo "true"; else echo "false"; fi | ||
false | false | ||
</ | </pre> | ||
|- | |- | ||
|<code>-z</code> | |<code>-z</code> | ||
|returns true if the string is null | |returns true if the string is null | ||
|< | |<pre> | ||
$ a=""; b="foobar"; if [ -z "$a" ]; then echo "true"; else echo "false"; fi | $ a=""; b="foobar"; if [ -z "$a" ]; then echo "true"; else echo "false"; fi | ||
true | true | ||
| Line 263: | Line 433: | ||
$ a=""; b="foobar"; if [ -z "$b" ]; then echo "true"; else echo "false"; fi | $ a=""; b="foobar"; if [ -z "$b" ]; then echo "true"; else echo "false"; fi | ||
false | false | ||
</ | </pre> | ||
|- | |- | ||
|<code>-n</code> | |<code>-n</code> | ||
|returns true if the string is NOT null | |returns true if the string is NOT null | ||
|< | |<pre> | ||
$ a=""; b="foobar"; if [ -n "$a" ]; then echo "true"; else echo "false"; fi | $ a=""; b="foobar"; if [ -n "$a" ]; then echo "true"; else echo "false"; fi | ||
false | false | ||
| Line 274: | Line 444: | ||
$ a=""; b="foobar"; if [ -n "$b" ]; then echo "true"; else echo "false"; fi | $ a=""; b="foobar"; if [ -n "$b" ]; then echo "true"; else echo "false"; fi | ||
true | true | ||
</ | </pre> | ||
|} | |} | ||
| Line 291: | Line 461: | ||
|<code>-a</code> | |<code>-a</code> | ||
|Logical and (both conditions must be true for condition to be true) | |Logical and (both conditions must be true for condition to be true) | ||
|< | |<pre> | ||
if [ "$expr1" -a "$expr2" ] | if [ "$expr1" -a "$expr2" ] | ||
then | then | ||
| Line 298: | Line 468: | ||
echo "Either expr1 or expr2 is false." | echo "Either expr1 or expr2 is false." | ||
fi | fi | ||
</ | </pre> | ||
|- | |- | ||
|<code>-o</code> | |<code>-o</code> | ||
|Logical or (either condition must be true for condition to be true) | |Logical or (either condition must be true for condition to be true) | ||
|< | |<pre> | ||
if [ "$expr1" -o "$expr2" ] | if [ "$expr1" -o "$expr2" ] | ||
then | then | ||
| Line 310: | Line 480: | ||
echo "Both expr1 and expr2 are false." | echo "Both expr1 and expr2 are false." | ||
fi | fi | ||
</ | </pre> | ||
|} | |} | ||
| Line 325: | Line 495: | ||
{{Main|Bash Math#Operators}} | {{Main|Bash Math#Operators}} | ||
==Bash Scripts for Heavy Bash Users== | |||
See https://github.com/alexanderepstein/Bash-Snippets | |||
* weather | |||
* geoip info | |||
* currency | |||
* encryption/decryption | |||
* movies | |||
* cheat - finding command options and code pieces | |||
* taste - "find similar things to X" | |||
=Bash Keyboard Shortcuts= | =Bash Keyboard Shortcuts= | ||
| Line 373: | Line 554: | ||
http://www.tech-recipes.com/rx/636/bash-shell-script-iterate-through-array-values/ | http://www.tech-recipes.com/rx/636/bash-shell-script-iterate-through-array-values/ | ||
=Flags= | |||
{{Programs}} | {{Programs}} | ||
{{Unix Programs}} | {{Unix Programs}} | ||
{{Languages}} | {{Languages}} | ||
[[Category:Bash]] | |||
Latest revision as of 02:45, 30 March 2019
Bash Quick Reference: Bash/Quick
Bash Quick Prototype: Bash/Prototype
Bash Guide
Using Bash
Setting the default shell: http://www.unix.com/shell-programming-scripting/32664-how-change-default-shell-linux.html
Startup Process
Dot Files
Bash Scripting
Looping
Looping in bash is really simple, and convenient - you can use other unix commands (most obviously "ls") to create lists, and then loop over each element of those lists. For example, if I want to print out the name of every file in my home directory (granted, not very useful, but this is just an example), I can do this:
for i in `/bin/ls -1 $HOME`; do
echo $i
done
To do some serious bash looping kung-fu, check out Xargs.
Bash Loop One-Liner: Seq and Destroy
Sometimes, you want to do a bash loop, but you want to do it on the fly, so you don't have to fire up your text editor and make a bash script.
Seq to the rescue!
The seq command is a way of creating very simple numerical sequences:
$ seq 1 10 1 2 3 4 5 6 7 8 9 10
But seq has some other features that make it very handy (see the Seq page for a full list of examples).
Seq can be very easily combined with bash to create one-line for loops.
Let's pose a simple scenario: say you've imported a bunch of photos from your camera, and their naming convention looks like this:got a lit of photos like this:
IMG_0000.jpg IMG_0001.jpg IMG_0002.jpg IMG_0003.jpg IMG_0004.jpg IMG_0005.jpg IMG_0006.jpg IMG_0007.jpg IMG_0008.jpg IMG_0009.jpg IMG_0010.jpg IMG_0011.jpg IMG_0012.jpg IMG_0013.jpg IMG_0014.jpg IMG_0015.jpg IMG_0016.jpg IMG_0017.jpg IMG_0018.jpg IMG_0019.jpg IMG_0020.jpg IMG_0021.jpg IMG_0022.jpg IMG_0023.jpg IMG_0024.jpg IMG_0025.jpg IMG_0026.jpg IMG_0027.jpg IMG_0028.jpg IMG_0029.jpg IMG_0030.jpg IMG_0031.jpg IMG_0032.jpg IMG_0033.jpg IMG_0034.jpg IMG_0035.jpg IMG_0036.jpg IMG_0037.jpg IMG_0038.jpg IMG_0039.jpg IMG_0040.jpg IMG_0041.jpg IMG_0042.jpg IMG_0043.jpg IMG_0044.jpg IMG_0045.jpg IMG_0046.jpg IMG_0047.jpg IMG_0048.jpg IMG_0049.jpg IMG_0050.jpg |
Now, let's say we want to move some photos to another folder, but we only want to move the odd-numbered photographs starting at 10 and ending at 40.
We can whip up a quick seq command that'll give us even numbers from 10 to 40:
$ seq 10 2 40
But we need the whole thing to be formatted into a comma-separated list, so we can feed it to a bash command, like mv {this,that} the_other/.. So let's use the -s flag:
$ seq -s, 10 2 40 10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,
Now we can use bash's backticks to plop that command in the middle of another mv command:
$ mv directory1/IMG_00{`seq -s, 10 2 40`}.jpg directory2/.
which unfolds to:
mv directory1/IMG_0010.jpg directory2/. mv directory1/IMG_0012.jpg directory2/. mv directory1/IMG_0014.jpg directory2/. mv directory1/IMG_0016.jpg directory2/. mv directory1/IMG_0018.jpg directory2/. mv directory1/IMG_0020.jpg directory2/. mv directory1/IMG_0022.jpg directory2/. mv directory1/IMG_0024.jpg directory2/. mv directory1/IMG_0026.jpg directory2/. mv directory1/IMG_0028.jpg directory2/. mv directory1/IMG_0030.jpg directory2/. mv directory1/IMG_0032.jpg directory2/. mv directory1/IMG_0034.jpg directory2/. mv directory1/IMG_0036.jpg directory2/. mv directory1/IMG_0038.jpg directory2/. mv directory1/IMG_0040.jpg directory2/. |
Voila!
But what if the range of file numbers strides 100? If you wanted to go from 80 to 120, you would end up with mismatching zero-padding. To get around this, you could either force seq to output all numbers with a fixed width (using the -w flag), or you could get more fancy by specifying a printf (print format) string for seq to use when printing each number (via the -f flag in seq).
Let's repeat the example, but this time using the printf approach. First, we want to print a 4-digit number that is zero-padded, meaning our printf string is going to be %04g. Now the seq command looks like:
$ seq -s, -f'%04g' 80 2 120 0080,0082,0084,0086,0088,0090,0092,0094,0096,0098,0100,0102,0104,0106,0108,0110,0112,0114,0116,0118,0120,
(Note we could have also used the printf string 'IMG_%04g.jpg' to make things a little more compact.)
Now we can feed that directly to the mv command:
$ mv directory1/IMG_{`seq -s, -f'%04g' 80 2 120`}.jpg directory2/.
which unfolds into the set of bash commands:
mv directory1/IMG_0080.jpg directory2/. mv directory1/IMG_0082.jpg directory2/. mv directory1/IMG_0084.jpg directory2/. mv directory1/IMG_0086.jpg directory2/. mv directory1/IMG_0088.jpg directory2/. mv directory1/IMG_0090.jpg directory2/. mv directory1/IMG_0092.jpg directory2/. mv directory1/IMG_0094.jpg directory2/. mv directory1/IMG_0096.jpg directory2/. mv directory1/IMG_0098.jpg directory2/. mv directory1/IMG_0100.jpg directory2/. mv directory1/IMG_0102.jpg directory2/. mv directory1/IMG_0104.jpg directory2/. mv directory1/IMG_0106.jpg directory2/. mv directory1/IMG_0108.jpg directory2/. mv directory1/IMG_0110.jpg directory2/. mv directory1/IMG_0112.jpg directory2/. mv directory1/IMG_0114.jpg directory2/. mv directory1/IMG_0116.jpg directory2/. mv directory1/IMG_0118.jpg directory2/. mv directory1/IMG_0120.jpg directory2/. |
Voila!
You can find more information about seq, and how to couple it with other Unix utilities, at the Seq page on my wiki.
Logical Operators
NOTE: the use of double brackets for logical condition checks is highly recommended.
There are several logical operators available for checking conditions in bash.
These can be tested using a simple "if" statement. In bash, if statements are of the form:
if [[ condition ]]; then
cmd
else
cmd2
fi
The spaces between the brackets and the condition are essential.
A comprehensive list of logical condition checks is here: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
Integer Operators
| Operator | Meaning | Example |
|---|---|---|
-eq
|
returns true if arguments are equal | $ a=1; b=1; if [[ "$a" -eq "$b" ]]; then echo "true"; else echo "false"; fi true $ a=1; b=2; if [[ "$a" -eq "$b" ]]; then echo "true"; else echo "false"; fi false |
-ne
|
returns true if arguments are not equal | $ a=1; b=1; if [[ "$a" -ne "$b" ]]; then echo "true"; else echo "false"; fi false $ a=1; b=2; if [[ "$a" -ne "$b" ]]; then echo "true"; else echo "false"; fi true |
-gt
|
returns true if argument 1 is greater than argument 2 | $ a=5; b=10; if [[ "$a" -gt "$b" ]]; then echo "true"; else echo "false"; fi false |
-ge
|
returns true if argument 1 is greater than or equal to argument 2 | $ a=15; b=10; if [[ "$a" -ge "$b" ]]; then echo "true"; else echo "false"; fi true $ a=10; b=10; if [[ "$a" -ge "$b" ]]; then echo "true"; else echo "false"; fi true |
-lt
|
returns true if argument 1 less than argument 2 | $ a=5; b=10; if [[ "$a" -lt "$b" ]]; then echo "true"; else echo "false"; fi true |
-le
|
returns true if argument 1 less than or equal to argument 2 | $ a=15; b=10; if [[ "$a" -le "$b" ]]; then echo "true"; else echo "false"; fi false $ a=10; b=10; if [[ "$a" -le "$b" ]]; then echo "true"; else echo "false"; fi true |
\<
|
returns true if argument 1 less than argument 2
this needs to be escaped with a \ if it occurs inside single brackets; otherwise it can appear between double bracket or between double parentheses |
$ a=10; b=10; if [ "$a" \< "$b" ]; then echo "true"; else echo "false"; fi false $ a=10; b=10; if [[ "$a" < "$b" ]]; then echo "true"; else echo "false"; fi false $ a=10; b=10; if (( "$a" < "$b" )); then echo "true"; else echo "false"; fi false |
<=
|
returns true if argument 1 less than or equal to argument 2
this operator needs to go inside double parentheses |
$ a=10; b=10; if (( "$a" <= "$b" )); then echo "true"; else echo "false"; fi true |
>
|
returns true if argument 1 greater than argument 2
this needs to be escaped with a \ if it occurs inside single brackets; otherwise it can appear between double bracket or between double parentheses |
$ z=10; zz=1000; $ if [ zz \> z ]; then echo "true"; else echo "false"; fi true $ if [[ zz > z ]]; then echo "true"; else echo "false"; fi true |
>=
|
returns true if argument 1 greater than or equal to argument 2
this operator needs to go inside double parentheses |
$ a=50; b=10; if (( $a >= $b )); then echo "true"; else echo "false"; fi true |
String Operators
| Operator | Meaning | Example |
|---|---|---|
=
|
returns true if two strings are equal | $ a=foo; b=foo; if [[ "$a" = "$b" ]]; then echo "true"; else echo "false"; fi true $ a=foo; b=bar; if [[ "$a" = "$b" ]]; then echo "true"; else echo "false"; fi false |
==
|
returns true if two strings are equal; equivalent to =
|
$ a=foo; b=foo; if [[ "$a" == "$b" ]]; then echo "true"; else echo "false"; fi true $ a=foo; b=bar; if [[ "$a" == "$b" ]]; then echo "true"; else echo "false"; fi false Note the difference between quoting a string and not quoting a string: [[ $a == b* ]] # returns true if $a starts with b (pattern matching) [[ $a == "b*" ]] # returns true if $a is literally equal to b* (literal matching) |
!=
|
returns true if strings are not equal | $ a=foo; b=bar; if [[ "$a" != "$b" ]]; then echo "true"; else echo "false"; fi true |
<
|
returns true if argument 1 is less than (alphabetically) argument 2; capitals come before non-capitals | $ a=foo; b=bar; if [[ "$a" < "$b" ]]; then echo "true"; else echo "false"; fi false $ a=Foo; b=bar; if [[ "$a" < "$b" ]]; then echo "true"; else echo "false"; fi true $ a=bar; b=foo; if [[ "$a" < "$b" ]]; then echo "true"; else echo "false"; fi true |
>
|
returns true if argument 1 is greater than (alphabetically) argument 2; capitals come before non-capitals | $ a=foo; b=bar; if [[ "$a" > "$b" ]]; then echo "true"; else echo "false"; fi true $ a=Foo; b=bar; if [[ "$a" > "$b" ]]; then echo "true"; else echo "false"; fi false |
-z
|
returns true if the string is null | $ a=""; b="foobar"; if [ -z "$a" ]; then echo "true"; else echo "false"; fi true $ a=""; b="foobar"; if [ -z "$b" ]; then echo "true"; else echo "false"; fi false |
-n
|
returns true if the string is NOT null | $ a=""; b="foobar"; if [ -n "$a" ]; then echo "true"; else echo "false"; fi false $ a=""; b="foobar"; if [ -n "$b" ]; then echo "true"; else echo "false"; fi true |
Compound Operators
You can combine logical operators using and/or operators:
| Operator | Meaning | Example |
|---|---|---|
-a
|
Logical and (both conditions must be true for condition to be true) | if [ "$expr1" -a "$expr2" ] then echo "Both expr1 and expr2 are true." else echo "Either expr1 or expr2 is false." fi |
-o
|
Logical or (either condition must be true for condition to be true) | if [ "$expr1" -o "$expr2" ] then echo "Either expr1 or expr2 is true." else echo "Both expr1 and expr2 are false." fi |
Basic Math
Complex Math
Math Operators
Bash Scripts for Heavy Bash Users
See https://github.com/alexanderepstein/Bash-Snippets
- weather
- geoip info
- currency
- encryption/decryption
- movies
- cheat - finding command options and code pieces
- taste - "find similar things to X"
Bash Keyboard Shortcuts
Editing Shortcuts
The following are keyboard shortcuts for easy navigation/editing of commands that are on the Bash command line.
Movement
- C-a - Move to beginning of line
- C-e - Move to end of line
- M-f - Move forward 1 word
- M-b - Move backward 1 word
- C-f - Move forward 1 character
- C-b - Move backward 1 character
Cutting and Pasting
- C-k - kill (cut) from cursor to end of line
- C-w - kill (cut) from cursor to previous whitespace
- C-y - yank (paste) previously killed text at cursor
Uncategorized
- C-L - clear screen, reprint current line at top
- C-u - undo last edit
- C-d - delete character under cursor
References
Floating point math in the shell:
http://www.novell.com/coolsolutions/tools/17043.html
Fast bash math:
http://www.bytemycode.com/snippets/snippet/350/
Bash script iterate through array of values
http://www.tech-recipes.com/rx/636/bash-shell-script-iterate-through-array-values/
Flags
| GNU/Linux/Unix the concrete that makes the foundations of the internet.
Compiling Software · Upgrading Software Category:Build Tools · Make · Cmake · Gdb Bash Bash · Bash/Quick (Quick Reference) · Bash Math Text Editors Text Manipulation Command Line Utilities Aptitude · Diff · Make · Patch · Subversion · Xargs Security SSH (Secure Shell) · Gpg (Gnu Privacy Guard) · Category:Security Networking Linux/SSH · Linux/Networking · Linux/File Server Web Servers
|
