I’ve been slowly making my way through O’Reilly’s Bash Cookbook: Solutions and Examples for Bash Users, 2nd edition, by Carl Albing & JP Vossen. It’s a great book but is enormous and not really structured for reading from beginning to end, as much as for referring to to solve a specific problem. I doubt I will ever finish it. But, there are a lot of great factoids in there! Last year, I read Packt’s Mastering Embedded Linux Programming, second edition, by Chris Simmonds, as well as Embedded Linux Development Using Yocto Project, second edition, by Alex Gonzalez (both of which I should do reviews on), and picked up a few of the commands I mention below in those books.
I learned Unix shell commands first on a DEC Vax 11-780 starting about 1984 at college, and then more over time using various distros of Linux from maybe 1997 onward. I’ll admit that most of what I know about ‘sh’ and ‘bash’ are from long ago.
Of course, time does not stand still, and though much of what I learned way back in the 1980s still applies, there is a lot that is new. Here are some cool examples of bash, GNU, and Ubuntu command line programs, as well as useful shell syntax, that I’ve picked up lately:
- lsb_release
Find out which release of Ubuntu you are on:$ lsb_release -sc bionic Or: $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.3 LTS Release: 18.04 Codename: bionic
- uname
Find out exactly what Linux kernel you’re running (without having to dig through ‘dmesg’):$ uname -a Linux Pallas 5.0.0-27-generic #28~18.04.1-Ubuntu SMP Thu Aug 22 03:00:32 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
- lastb
See when (and/or if) anyone else has recently tried and failed to log in to your box. - lsusb, lsblk, lsof, lshw, lsipc, lsmem, lsattr, lslocks, lspci, …
There are a number of super helpful commands to find out more about USB devices, block devices, open files, hardware, etc. sometimes ‘sudo’ is needed to get a full picture. - htop
Show information (similar to ‘top’) for all processes, but also show a pseudo-graphical CPU load graph per CPU core, as well as color-coding to make it more readable… - type
Searches your environment (including aliases, keywords, the path) for a command; -a shows all matches:$ type -a ls ls is aliased to `ls --color=auto' ls is /bin/ls
- which
Similar to type, but only searches the path:$ which ls /bin/ls
- apropos
Searches man pages for a regular expression; helpful if you forget the exact name of a command:$ apropos games intro (6) - introduction to games sol (6) - a collection of card games which are easy to play with the aid of a mouse.
- locate
Searches a database about the system (which is updated by a cron job):$ locate grub.cfg /boot/grub/grub.cfg /etc/grub.d/backup/boot_grub/grub.cfg /usr/share/doc/grub-common/examples/grub.cfg
- stat
Get very detailed information about a file:$ stat /boot/grub/grub.cfg File: /boot/grub/grub.cfg Size: 10542 Blocks: 24 IO Block: 4096 regular file Device: 805h/2053d Inode: 2097154 Links: 1 Access: (0444/-r--r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2019-09-11 11:28:16.269000000 -0700 Modify: 2019-09-10 10:13:49.739865322 -0700 Change: 2019-09-10 10:13:49.751865322 -0700 Birth: -
- printf
There’s a command line (or scriptable) printf? Who knew?$ printf '%s = %d\n' Columns $COLUMNS Columns = 157
- redirecting stdout and stderr
'command &> file' or 'command >& file'
are simpler ways to do the old syntax:
'command > file 2>&1'
All these will redirect both stdout and stderr to the file.
- redirecting output from multiple commands to the same file
Both:'{ cmd1; cmd2; cmd3; ... cmdN; } > file'
or
'(cmd1; cmd2; cmd3; ... cmdN) > file'
will redirect all output from each command to the same file. In the past I have resorted to placing multiple commands in a shell script, then running that and redirecting its output. Now I know better!
Note that using parentheses actually cause the commands to run in a subshell, so if they modify the environment, any changes will be lost in the current shell. Braces, however, run in the current shell. - alternate way to pass arguments to a command from another
I’m familiar with the old backtick (`) way to run a command and have the result of that be an argument to another command:rm `find . -name '*.bak'`
but there is a more modern way which is nestable:
rm $(find . -name '*.bak')
- more to come…