# Bash Tips ## Resources ### [The art of the command line](https://github.com/jlevy/the-art-of-command-line) ### [Google's bash style guide](https://google.github.io/styleguide/shellguide.html#s1.1-which-shell-to-use) ## Notes ### Show the name of the command running on each port on [[macOS]] [Credit](https://x.com/seldo/status/1823126087423099192) to Laurie Voss (@seldo) on X *This absurd "one-liner" will show you the name of the command running on each port on MacOS, which is something I need to do constantly so leaving it here:* ```bash sudo lsof -iTCP -sTCP:LISTEN -n -P \ | awk 'NR>1 {print $9, $1, $2}' \ | sed 's/.*://' \ | while read port process pid; do echo "Port $port: $(ps -p $pid -o command= \ | sed 's/^-//') (PID: $pid)"; done \ | sort -n ``` ### Remove ANSI color codes from stdout log output ```bash sed -r "s/\x1B\[(([0-9]{1,2})?(;)?([0-9]{1,2})?)?[m,K,H,f,J]//g" file_name ``` [Source](https://stackoverflow.com/a/30938702) Example usage with [[Cargo]] test: ```bash cargo test -p smoketest user_recvs_jit_from_user | tee | sed -r 's/\x1B\[(([0-9]{1,2})?(;)?([0-9]{1,2})?)?[m,K,H,f,J]//g' | tee log/log.txt ``` ### [Using arguments from the previous command](https://stackoverflow.com/q/4009412) `!!` gives you the entire last command. `!
gives you the last argument of the last command. `!:n` gives you the nth token of the last command, 0 indexed. ```bash $ cat file.txt $ echo !:0 # Expands to `echo cat` $ cat file.txt $ echo !:1 # Expands to `echo file.txt` $ TEMP=1 cat file.txt $ echo !:0 # Expands to `echo TEMP=1` ``` ### (Guide) [Bash parameter expansion](https://linuxhint.com/bash_parameter_expansion/) So you can know wtf is going on in the PATH assignment here: ```bash if [[ ! "$PATH" == *$(brew --prefix)/opt/fzf/bin* ]]; then PATH="${PATH:+${PATH}:}/opt/homebrew/opt/fzf/bin" fi ``` ### If / elif / else syntax ```bash if [[ "bash" == $0 ]]; then echo "Running bash" elif [[ "zsh" == $0 ]]; then echo "Running zsh" else echo "Running something else: $0" fi ``` ### Running scripts that set environment variables - `. env.sh` or `source env.sh` actually updates the env variables - Check with `env` - `./env.sh` does not ### [Defining a Bash Variable With or Without ‘export’](https://www.baeldung.com/linux/bash-variables-export) - *Shell variables (defined without export) are like local variables that we can access only within that shell.* - *Environment variables (defined with export) are like global variables that we can access within the defining shell and all its child shells, processes, and commands.* ### Run a binary in the background https://www.linuxquestions.org/questions/linux-newbie-8/how-to-run-any-binary-in-background-background-process-218120/ ```bash ./daemon & ``` OR ```bash ./daemon ^Z daemon suspended bg # run in background ``` ### Examining binaries ```bash $ xxd Body.data | head -n15 00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000040: f74d 7001 0000 0000 ffff ffff 2000 0000 .Mp......... ... 00000050: 0000 0000 da02 0000 ffff ffff ffff ffff ................ 00000060: 9480 0000 9080 0000 443b 0400 78da ecbd ........D;..x... 00000070: 6b8c 2457 961e 26ed 6ab5 6fc9 300c c382 k.$W..&.j.o.0... 00000080: 21e3 aac7 10ab b455 3df9 7eb0 67da aa6e !......U=.~.g..n 00000090: 72d8 3d7c 0cc5 2667 b05a 8c1b 3723 6e66 r.=|..&g.Z..7#nf 000000a0: 5c56 44dc e4bd 1155 9dc4 1a18 6261 9918 \VD....U....ba.. 000000b0: 717f 505c db4b 2cb4 c66a e911 966b 4382 q.P\.K,..j...kC. 000000c0: b570 0bd6 2f75 f71a ae69 0c2c ff31 6003 .p../u...i.,.1`. 000000d0: b6e1 010c 0102 2c03 fee3 1f86 1fe7 dc1b ......,......... 000000e0: 9195 8f88 cc8c c81b 9955 2407 c3ae aacc .........U$..... ``` Source: https://fmentzer.github.io/posts/2020/dictionary/ ### [Examine dynamic linking requirements of binary executable](https://users.rust-lang.org/t/compile-on-ubuntu-and-run-on-rhel/11727/4) e.g. after running `cargo run --release` ```bash $ readelf -V target/release/hellorustsgx Version symbols section '.gnu.version' contains 75 entries: Addr: 0x0000000000000f40 Offset: 0x000f40 Link: 5 (.dynsym) 000: 0 (*local*) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 004: 2 (GLIBC_2.2.5) 3 (GCC_3.3) 4 (GLIBC_2.2.5) 4 (GLIBC_2.2.5) 008: 0 (*local*) 2 (GLIBC_2.2.5) 4 (GLIBC_2.2.5) 5 (GLIBC_2.18) 00c: 6 (GLIBC_2.3.4) 2 (GLIBC_2.2.5) 7 (GCC_3.0) 4 (GLIBC_2.2.5) 010: 7 (GCC_3.0) 7 (GCC_3.0) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 014: 4 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 4 (GLIBC_2.2.5) 4 (GLIBC_2.2.5) 018: 4 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 8 (GCC_4.2.0) 01c: 4 (GLIBC_2.2.5) 4 (GLIBC_2.2.5) 7 (GCC_3.0) 2 (GLIBC_2.2.5) 020: 2 (GLIBC_2.2.5) 9 (GLIBC_2.3) 4 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 024: 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 0 (*local*) 028: a (GLIBC_2.3) b (GLIBC_2.14) 7 (GCC_3.0) 4 (GLIBC_2.2.5) 02c: 4 (GLIBC_2.2.5) 4 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 030: 4 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) c (GLIBC_2.28) 034: 4 (GLIBC_2.2.5) 7 (GCC_3.0) 2 (GLIBC_2.2.5) 7 (GCC_3.0) 038: 4 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 03c: 2 (GLIBC_2.2.5) 4 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 040: 4 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 0 (*local*) 7 (GCC_3.0) 044: 2 (GLIBC_2.2.5) 7 (GCC_3.0) 4 (GLIBC_2.2.5) 4 (GLIBC_2.2.5) 048: 4 (GLIBC_2.2.5) 7 (GCC_3.0) 2 (GLIBC_2.2.5) Version needs section '.gnu.version_r' contains 4 entries: Addr: 0x0000000000000fd8 Offset: 0x000fd8 Link: 6 (.dynstr) 000000: Version: 1 File: ld-linux-x86-64.so.2 Cnt: 1 0x0010: Name: GLIBC_2.3 Flags: none Version: 9 0x0020: Version: 1 File: libpthread.so.0 Cnt: 1 0x0030: Name: GLIBC_2.2.5 Flags: none Version: 4 0x0040: Version: 1 File: libgcc_s.so.1 Cnt: 3 0x0050: Name: GCC_4.2.0 Flags: none Version: 8 0x0060: Name: GCC_3.0 Flags: none Version: 7 0x0070: Name: GCC_3.3 Flags: none Version: 3 0x0080: Version: 1 File: libc.so.6 Cnt: 6 0x0090: Name: GLIBC_2.28 Flags: none Version: 12 0x00a0: Name: GLIBC_2.14 Flags: none Version: 11 0x00b0: Name: GLIBC_2.3 Flags: none Version: 10 0x00c0: Name: GLIBC_2.3.4 Flags: none Version: 6 0x00d0: Name: GLIBC_2.18 Flags: none Version: 5 0x00e0: Name: GLIBC_2.2.5 Flags: none Version: 2 ``` ### Examine requirements using `ppd` ### Count lines of code ```bash brew install tokei tokei . ``` ### [Difference between `>>` and `tee -a`](https://unix.stackexchange.com/a/464654) **TL;DR:** `tee -a` is superior to `>>` There's no difference in the sense that the data _in the file_ will be the same if `echo` and `tee` are executed successfully and if the file is writable by the current user. The `tee` command would additionally produce output on _its_ standard output, showing the text that would also be appended to the file. This would not happen in the first command. Another difference is that if the file can _not_ be written to, then the first command, with the redirection, would not even run the `echo`, whereas the `echo` _would_ run in the second command, but `tee` would fail in writing to the file (`tee` would still produce text on the terminal though). This could be significant in the case where you run some long running process that produces output: ``` long_running_thing >>file ``` This would not even start `long_running_thing` if `file` was not writable. ``` long_running_thing | tee -a file ```