I have reading this book (1st edit – quite old) in the last months after breakfast. So I am taking some notes. I think they are things useful and I should use them. So try to write, understand, remember and use.
I am using bash 5.1.0(1)-rc3
$ bash --version GNU bash, version 5.1.0(1)-rc3 (x86_64-pc-linux-gnu)
1- Quoting
Shell quoting: Enclose a string in single quotes unless it contains elements that you want the shell to interpolate
$ echo John has $100 note?! John has 00 note?! $ echo "John has $100 note?!" John has 00 note?! $ echo 'John has $100 note?!' John has $100 note?!
You can’t embed a single quote inside single quotes even with a backslash. Nothing is interpolated inside single quotes. Workaround is using double quotes with escapes or, escaping a single quote outside of surrounding single quotes.
$ echo 'John doesn't have $100 notes' ^C $ $ echo "John doesn't have $100 notes" John doesn't have 00 notes $ $ echo "John doesn't have \$100 notes" John doesn't have $100 notes $ $ echo 'John doesn'\''t have $100 notes' John doesn't have $100 notes $
2- Standard Output/Input
Redirect output from “ls”: It can be confusing when redirecting output from “ls” to a file and then read it as you dont see the expected format. Using “-C” you ensure the redirection will be based on “Colummns”. By default (-1), the output will be based on lines.
$ ls -ltr total 92 -rw-r--r-- 1 tomas tomas 72533 Jul 27 2016 jabber.py -rw-r--r-- 1 tomas tomas 16087 Jul 27 2016 anotify.py drwxr-xr-x 2 tomas tomas 4096 Dec 10 2017 autoload $ ls anotify.py autoload jabber.py $ ls > /tmp/test.txt $ cat /tmp/test.txt --> You would expect just one line like "ls"???? anotify.py autoload jabber.py $ $ ls -C > /tmp/test2.txt $ cat /tmp/test2.txt --> Yes, this is the same output of standard "ls" anotify.py autoload jabber.py $ ls -C anotify.py autoload jabber.py $ ls -1 anotify.py autoload jabber.py $
Redirect output and error to different files:
$ ls -ltr /boot/* > /tmp/test-out.txt 2> /tmp/test-err.txt $ $ cat /tmp/test-out.txt ... -rw-r--r-- 1 root root 73210069 Nov 28 11:10 /boot/initrd.img-5.9.0-1-amd64 -rw-r--r-- 1 root root 234724 Nov 28 11:10 /boot/config-5.9.0-1-amd64 /boot/grub: total 2379 ... -rw-r--r-- 1 root root 2394102 Nov 14 18:12 unicode.pf2 -r--r--r-- 1 root root 8362 Nov 28 10:53 grub.cfg $ $ cat /tmp/test-err.txt ls: cannot open directory '/boot/efi': Permission denied ls: cannot open directory '/boot/lost+found': Permission denied $
Redirect output and error to same file, use “>&“. Other option is “$ program > outfile 2>&1“
$ ls -ltr /boot/* >& /tmp/test-both.txt $ $ cat /tmp/test-both.txt ... -rw-r--r-- 1 root root 73210069 Nov 28 11:10 /boot/initrd.img-5.9.0-1-amd64 -rw-r--r-- 1 root root 234724 Nov 28 11:10 /boot/config-5.9.0-1-amd64 ls: cannot open directory '/boot/efi': Permission denied ls: cannot open directory '/boot/lost+found': Permission denied /boot/grub: total 2379 ... -rw-r--r-- 1 root root 2394102 Nov 14 18:12 unicode.pf2 -r--r--r-- 1 root root 8362 Nov 28 10:53 grub.cfg $ $ ls -ltr /boot/* > /tmp/test3.txt ls: cannot open directory '/boot/efi': Permission denied ls: cannot open directory '/boot/lost+found': Permission denied $
Grouping output from several commands: Use () for grouping them
:/tmp/aaa/bbb$ (ls -ltr; pwd; cd ..; ls -ltr; pwd) > /tmp/all.txt :/tmp/aaa/bbb$ :/tmp/aaa/bbb$ cat /tmp/all.txt total 0 -rw-r--r-- 1 tomas tomas 0 Nov 28 16:28 b.txt /tmp/aaa/bbb total 4 drwxr-xr-x 2 tomas tomas 4096 Nov 28 16:28 bbb -rw-r--r-- 1 tomas tomas 0 Nov 28 16:28 aaa.txt /tmp/aaa :/tmp/aaa/bbb$
“tee“: read from standard input and write to standard output and files:
:/tmp/bbb$ ls -ltr total 32 -rw-r--r-- 1 tomas tomas 30 Nov 28 15:29 test.txt -rw-r--r-- 1 tomas tomas 32 Nov 28 15:30 test2.txt -rw-r--r-- 1 tomas tomas 58 Nov 28 15:38 error.txt -rw-r--r-- 1 tomas tomas 935 Nov 28 15:57 test-out.txt -rw-r--r-- 1 tomas tomas 121 Nov 28 15:57 test-err.txt -rw-r--r-- 1 tomas tomas 1056 Nov 28 15:59 test-both.txt -rw-r--r-- 1 tomas tomas 935 Nov 28 16:00 test3.txt -rw-r--r-- 1 tomas tomas 1 Nov 28 16:47 all.txt -rw-r--r-- 1 tomas tomas 0 Nov 28 16:52 a.a -rw-r--r-- 1 tomas tomas 0 Nov 28 16:52 a.aa -rw-r--r-- 1 tomas tomas 0 Nov 28 16:52 a.aaa :/tmp/bbb$ :/tmp/bbb$ :/tmp/bbb$ find . -name '*.txt' ./all.txt ./test.txt ./test3.txt ./test2.txt ./test-out.txt ./error.txt ./test-both.txt ./test-err.txt :/tmp/bbb$ :/tmp/bbb$ find . -name '.txt' | tee /tmp/tee.txt ./all.txt ./test.txt ./test3.txt ./test2.txt ./test-out.txt ./error.txt ./test-both.txt ./test-err.txt :/tmp/bbb$ :/tmp/bbb$ cat /tmp/tee.txt ./all.txt ./test.txt ./test3.txt ./test2.txt ./test-out.txt ./error.txt ./test-both.txt ./test-err.txt :/tmp/bbb$
Here-Doc: use \EOF to turn off shell scripting features inside here-doc.
:/tmp/aaa$ bash here.txt bb bb $2 :/tmp/aaa$ bash here.txt aa aa $1 :/tmp/aaa$ :/tmp/aaa$ cat here.txt here-doc example grep $1 <<\EOF name note aa $1 bb $2 cc $3 EOF :/tmp/aaa$
“$?”return non-zero if the last command fails.
:/tmp$ pwd /tmp :/tmp$ echo $? 0
“&&” run next program if the preceding program worked (logic and)
:/tmp$ ./test && date bash: ./test: No such file or directory :/tmp$ :/tmp$ pwd && date /tmp Sat 28 Nov 17:20:50 GMT 2020 :/tmp$
“||” (logic or)
:/tmp/aaa$ ./test || ( printf "%b" "Failed.\n") bash: ./test: No such file or directory Failed. :/tmp/aaa$
nohup: run job in background and exit shell before finishing job.
$ nohup ./long-script &
for loop:
:/tmp/aaa$ for FILE in bbb/* do if [ -f $FILE ] then cat $FILE fi done a file b file c file :/tmp/aaa$ ls -ltr bbb/ total 12 -rw-r--r-- 1 tomas tomas 7 Nov 28 17:30 a.txt -rw-r--r-- 1 tomas tomas 7 Nov 28 17:30 b.txt -rw-r--r-- 1 tomas tomas 7 Nov 28 17:31 c.txt