Personal Unix shell cheat sheet. It contains:
- zsh and bash shell tricks
- nontrivial commands
Personal Unix shell cheat sheet. It contains:
bash |
zsh |
Description |
---|---|---|
${parameter:-word} |
${parameter:-word} |
If parameter is unset or null, the expansion of word is substituted. |
${parameter:=word} |
${parameter:=word} |
If parameter is unset or null, the expansion of word is assigned to parameter. |
${parameter:?message} |
${parameter:?message} |
If parameter is unset or null, the expansion of message is written to the standard error and the shell, if it is not interactive, exits. |
${parameter:+word} |
${parameter:+word} |
If parameter is unset or null, nothing is substituted, otherwise the expansion of word is substituted (it works like masking parameter if it is set). |
${parameter:n} |
${parameter:n} |
Expand to the string started at the n th term of parameter (offset is zero based). |
${parameter: -n} |
${parameter: -n} |
Expand to the string started at the end-n th term of parameter (offset is zero based) (Note that a negative offset must be separated from the colon by at least one space to avoid being confused with the :- expansion). |
${parameter:n:m} |
${parameter:n:m} |
Expand to the m -sized string started at the n th term of parameter (offset is zero based). |
${parameter:n:-m} |
${parameter:n:-m} |
Expand to the string started at the n th term and ended at the end-m th term of parameter (offset is zero based). |
${parameter##*.} |
${parameter##*.} |
Remove prefix greedily. |
${parameter#*.} |
${parameter#*.} |
Remove prefix lazily. |
${parameter/#foo/bar} |
${parameter/#foo/bar} |
Prefix substitution. It doesn't match substring. For that, you can use the * wildcard (backreference is not possible, though). |
${parameter%%.*} |
${parameter%%.*} |
Remove suffix greedily. |
${parameter%.*} |
${parameter%.*} |
Remove suffix lazily. |
${parameter/%foo/bar} |
${parameter/%foo/bar} |
Suffix substitution. It doesn't match substring. For that, you can use the * wildcard (backreference is not possible, though). |
${parameter/foo/bar} |
${parameter/foo/bar} |
First-occurrence substitution. It doesn't match substring. For that, you can use the * wildcard (backreference is not possible, though). |
${parameter//foo/bar} |
${parameter//foo/bar} |
Global substitution. It doesn't match substring. For that, you can use the * wildcard (backreference is not possible, though). |
${parameter^^} |
${foo:u} |
Upper case. |
${parameter^} |
First-letter upper case. | |
${parameter,,} |
${foo:l} |
Lower case. |
${parameter,} |
First-letter lower case. | |
{foo,bar} |
{foo,bar} |
List expansion. |
{1..10} |
{1..10} |
Numeric sequence expansion. |
{a..z} |
{a..z} |
Character sequence expansion. |
$(command) |
$(command) |
Command expansion. |
`command` |
`command` |
Command expansion (deprecated). |
<(command) |
<(command) |
Process substitution (expand to the the path of a temporary file whose content is the output of command ). |
/foo/bar* |
/foo/bar* |
Expand to anything starting with bar . |
/foo/bar?? |
/foo/bar?? |
Expand to anything starting with bar and with 2 any character (you can put ? as many as you want). |
/foo/[abc]* |
/foo/[abc]* |
Expand to anything starting with a , b , or c . |
/foo/[^abc]* |
/foo/[^abc]* |
Expand to anything not starting with a , b , or c . |
/foo/[a-f]* |
/foo/[a-f]* |
Expand to anything starting with any character between a a f . |
/foo/[0-7]* |
/foo/[0-7]* |
Expand to anything starting with any character between 0 a 7 . |
[[:xdigit:]] |
[[:xdigit:]] |
Hexadecimal digits: 0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f. |
[[:digit:]] |
[[:digit:]] |
Decimal digits: 0 1 2 3 4 5 6 7 8 9. |
[[:lower:]] |
[[:lower:]] |
Lower-case letters: a b c d e f g h i j k l m n o p q r s t u v w x y z. |
[[:upper:]] |
[[:upper:]] |
Upper-case letters: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z. |
[[:alpha:]] |
[[:alpha:]] |
[[:lower:]] and [[:upper:]] . |
[[:alnum:]] |
[[:alnum:]] |
[[:alpha:]] and [[:digit:]] . |
[[:punct:]] |
[[:punct:]] |
Punctuation characters: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~. |
[[:graph:]] |
[[:pragh:]] |
[[:alnum:]] and [[:punct:]] . |
[[:print:]] |
[[:print:]] |
[[:graph:]] and space. |
[[:blank:]] |
[[:blank:]] |
Space and tab. |
[[:space:]] |
[[:space:]] |
tab, newline, vertical tab, form feed, carriage return, and space. |
${PATH_TO_FILE:a} |
Simplifies the path by resolving . , .. , ~ ... |
|
${PATH_TO_FILE:A} |
Same as a , but follows symbolic links. |
|
${PATH_TO_FILE:e} |
Expand to the extension name. | |
${PATH_TO_FILE:r} |
Remove the extension name. | |
${PATH_TO_FILE:t} |
Tail: basename (with the extension). | |
${PATH_TO_FILE:h} |
Head/prefix, that is, the dir path. | |
!n |
!n |
Expand to n th first command. |
!-n |
!-n |
Expand to n th last command. |
!! |
!! |
Expand to last command. |
!-n:m |
!-n:m |
Expand to the m th argument of the n th last command. You can also use !n:m< to get the n th command in the commad history (this form is rarely used, though). |
!str |
!str |
Expand to last command starting with the string str . |
!* |
!* |
Expand to all arguments in the previous command. |
!^ |
!^ |
Expand to the first argument in the previous command. |
!$ |
!$ |
Expand to the last argument in the previous command. |
!:n |
!:n |
Expand to the n th argument in the previous command (0 is the command itself). |
!:n-m |
!:n-m |
Expand to the argument range n-m in the previous command. |
!#:* |
!#:* |
Expand to all arguments in the current command. |
!#:^ |
!#:^ |
Expand to the first argument in the current command. |
!#:$ |
!#:$ |
Expand to the last argument in the current command. |
!#:n |
!#:n |
Expand to the n th argument in the current command (0 is the command itself). |
!#:n-m |
!#:n-m |
Expand to the argument range n-m in the current command. |
( zsh exclusive. EXTENDED_GLOB must be set.) |
||
^foo |
Expand to everything but foo . |
|
^(foo|bar) |
Expand to everything but foo or bar (you can repeat it as many as you want). |
|
command foo < bar baz |
command foo < bar baz |
< treats the very next value (in this case, bar ) as a path to a file whose content is put within the STDIN of command . If it is already the default behavior of command , nothing changes |
command <<< "some text" |
command <<< "some text" |
<<< (called here string) puts "some text" within the STDIN of command . |
command > foo |
command > foo |
> redirects the STDOUT of command to the file path foo instead of printing it on the terminal (the default behavior). |
command >> foo |
command >> foo |
The same as the previous command, but append to foo if it already exists instead of overwriting it. |
command 2> foo |
command 2> foo |
2> redirects the STDERR of command to the file path foo instead of printing it on the terminal (the default behavior). |
command &> foo |
command &> foo |
> redirects both the STDERR and STDOUT of command to the file path foo instead of printing them on the terminal (the default behavior). |
command &>> foo |
command &>> foo |
The same as the previous command, but append to foo if it already exists instead of overwriting it. |
command1 foo | command2 |
command1 foo | command2 |
Put the STDOUT of command1 within the STDIN of command2 . |
bash |
zsh |
Description |
arr=("apple" "banana" "pineapple") |
arr=("apple" "banana" "pineapple") |
Initialize an array. |
arr+=("orange") |
arr+=("orange") |
Append element to arr . |
${arr[n]} |
${arr[n]} |
Return the n th element of the array. Bash is 0-based and a string is not treated as an array. Zsh is 1-based and a string is treated as an array. |
${arr[@]} |
${arr[@]} or ${(@)arr} |
Expand to all element in arr into different words, that is ${arr[1]} ${arr[2]} ... |
${arr[*]} |
${(j[c])arr} |
In bash, it expands to all element in arr into a single word, that is, ${arr[1]}c${arr[2]}... , where c is the first character defined in IFS. In zsh, this character is defined after the j flag. You can enclose this character with other pairs besides [] ((c) , {c} , <c> , ...). Alternatively, you can use a different character to enclose c (e.g., aca , :c: , scs , ...). |
(IFS="c"; joined="${arr[*]}") |
${(j:str:)arr} |
In zsh, join elements of arr with str between them. In bash, you need to create a subshell so the IFS modification takes effect only within this subshell (you can joint the array elements with a single character only). |
unset arr[n] |
unset "arr[n]" |
Remove the n th element in arr . Bash is 0-based while zsh is 1-based. |
Command | Description |
---|---|
lsmod |
Show the status of modules in the Linux Kernel. |
usermod |
A command used for modifying user account properties. |
-a|--append -G|--groups group user |
Modify a user's group membership. Adds the user to the group group. |
uname |
Print system information (kernel, computer architecture ...). |
lspci |
Print detailed information about all PCI (Peripheral Component Interconnect) buses and devices in the system, including graphics cards, network adapters, storage controllers, and more. Peripheral Component Interconnect (PCI) is a standard interface for connecting various hardware devices to a computer's motherboard. It is a local bus standard developed by Intel Corporation, and it provides a high-speed data path between the central processing unit (CPU) and attached devices. The PCI bus has evolved over time, and its successors include PCI-X and PCI Express (PCIe). |
-nn |
Show vendor and device ID as both numbers and names in the form vendorID:deviceID . The Device ID helps the operating system and drivers to recognize and distinguish between different models provided by the vendor. |
lscpu |
A "core" refers to an independent processing unit within a single physical CPU (Central Processing Unit) chip. Each core is capable of executing its own set of instructions independently of other cores. Modern CPUs often have multiple cores, allowing them to perform multiple tasks simultaneously. The nproc command prints the number of processing units available to the system. This includes both physical cores and virtual cores (threads) if the CPU supports technologies like Hyper-Threading. Hyper-Threading allows each physical core to appear as two logical cores to the operating system, enabling better utilization of resources. The term "socket" refers to a physical CPU socket on the motherboard. A socket is a mechanical component that provides a physical and electrical connection between the CPU and the motherboard. It's the slot where you insert the CPU. When lscpu displays information about sockets, it is indicating the number of physical CPU sockets present on the system. Each socket can contain one or more cores. |
apt-get download pkg |
Download pkg as a .deb . |
apt-file list pkg |
List files within pkg . |
apt-file search /path/to/file.h |
List packages that contain /path/to/file.h . |
apt-cache |
Get info in the APT cache. |
pkgnames |
Print all package names. |
show pkg |
Show information about pkg . |
rdepends [--installed] pkg |
Print dendency tree of pkg [limit the search to installed packages]. |
dpkg-deb -x /path/to/file.deb /path/to/dir/ |
Extract .deb file to /path/to/dir/. |
dpkg |
package manager for Debian. |
-l |
List installed packages. |
-L pkgname |
List files installed to your system from package-name. |
-i /path/to/file.deb |
Install .deb pkg. |
-S /path/to/file |
Find for package name that contains the file /path/to/file (it does the same as apt-file search . |
--audit |
Search for broken packages (return nothing if it wasn't found). |
--print-architecture |
Prints the architecture of the current system (both "x86_64" and "AMD64" are widely used to refer to the same 64-bit architecture). |
gpg |
GNU Privacy Guard. The GPG has two extensions for storing cryptographic keys, also known as, keyring files. /usr/share/keyrings and ~/.gnupg are some directories where you can find such GPG keys. There are two main types:
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
--import public_key.asc |
Import public_key.asc to ~/.gnupg/pubring.kbx . This file (or ~/.gnupg/pubring.gpg in older versions of GPG) is a keyring file that serves as a repository for storing multiple public keys. Every new public key, which usually comes from a PGP public key file (.asc ), is appended to this file. |
--list-public-keys|-k|--list-keys|--fingerprint|--check-sigs |
List imported and generated public keyring files on the default path, which is on ~/.gnupg/ . There are two main keyring files:
It follows an example /home/tapyu/.gnupg/pubring.kbx ------------------------------ pub rsa3072 2023-11-16 [SC] [expires: 2025-11-15] EFDBABBD3F246CF213F711EDB8699361831715DA uid [ unknown] Docker login sub rsa3072 2023-11-16 [E] [expires: 2025-11-15]
--fingerprint (it provides a clearer print!) and --check-sigs performs the same listing task.
¹: RSA (Rivest-Shamir-Adleman) is a widely used public-key cryptographic algorithm. |
--list-secret-keys|-K |
Same as --list-public-keys , but for secret/private keys. |
--show-keys /path/to/keyring_file.gpg
--show-keys /path/to/pgp_public_key_file.asc
|
Instead of printing GPG keys from the default keyring files (i.e., ~/.gnupg/{pubring.kbx,trustdb.gpg} ), print all GPG keys from /path/to/keyring-file.gpg or the public GPG key that the PGP public key file /path/to/pgp_public_key_file.asc represents. |
--delete-keys gpg-key-id |
Remove from ~/.gnupg/pubring.kbx . By using the GPG key ID in the last example, we can run gpg --delete-keys B8699361831715DA to delete it. A yes/no prompt will pop up. |
--delete-secret-keys gpg-key-id |
|
--generate-key |
Initiate an interactive process to generate a new key pair. A key pair consists of:
|
--full-generate-key |
Like --generate-key , but with much more details. |
--export-secret-keys -a|--armor "Real Name" > armored_private_key.asc |
Generate the ASCII-armored file armored_private_key.asc from a private key whose real name is Real Name . The --armor option stands for ASCII armor. It tells GPG to output the key or data in a format that is comprised of plain ASCII text, making it more human-readable and easily exchangeable. These plain text files are usually called armored files and use the armored_ filename prefix. |
[-o /path/to/keyring_file.gpg] --dearmor armored_pub_key.asc |
Convert the ASCII-armored file into a binary GPG keyring file and save it as armored_pub_key.asc.gpg [or /path/to/keyring_file.gpg ]. |
--export -a|--armor "Real Name"|gpg-key-id > public_key.asc |
Generate the GPG public key from the GPG public key ID or the "Real Name" value. |
--list-packets public_key.asc |
Inspect the public key packets and retrieve details like the user ID and key ID. |
--edit-key your_generated_gpg-id |
|
--sign|--detach-sig filename |
Sign a file with your GPG private key, thus generating a signature file (usually with extension .sig or .gpg ). Signature file is used for a different purpose than encryption and decryption: Its primary goal is to ensure the integrity and authenticity of the content, while encrypting/decrypting is to keep the content confidential (you don't even use signature files for encrypting/decrypting things). However, the same idea of public and private key is applied. The signature file is a cryptographic proof that the file has been signed by the holder of the private key associated with the GPG key pair. It is unique to both the content of the file and the private key. Others can then use your public key to verify the signature's authenticity. If --sign is used, gpg attaches a signature to the end of the file, creating a unique file that includes both the original data and the signature. Hence, the signed file can be shared as a single entity. On the other hand, if --detach-sig is used, gpg creates a detached signature, that is, a signature file that is separated from the original file. The signature file contains information about the digital signature but it doesn't include the actual content of the file. In either way, if the verification is successful, it provides assurance that the file has not been tampered with and was indeed signed by the private key associated with the public key used for verification. |
--default-key keyid_or_userid |
Use keyid_or_userid to sign. If omitted, the first private key listed will be used. |
--output custom_signature_filename |
If --output is not given, the actual output is filename.sig |
--local-user keyid_or_userid |
GPG will use the first private key for signing unless you specify the --local-user option. |
--recipient uid_or_keyID --encrypt file |
Encrypt file with the uid_or_keyID |
--output custom-filename |
(optional) output as custom-filename filename instead of putting to STDOUT. |
--decrypt attached-sigfile |
By using the private key, decrypt an encrypted message or an attached signature file (like unzip) and put it to SDTOUT. If the decrypted file is signed, the signature is also verified. Since private keys requires careful consideration, a passphrase is often required whenever you use private keys. The passphrase is defined when you generate a new key pair. The passphrase adds an additional layer of security, ensuring that even if the private key is obtained, an attacker would still need the passphrase to decrypt it. |
--output custom-filename |
(optional) output as custom-filename filename instead of putting to STDOUT. |
pass |
Besides encrypting/decrypting and signature authentication, another application is to manage passwords. pass is a simple password manager for Unix-like operating systems that stores encrypted passwords using GPG. |
list |
Displays a hierarchical list of all passwords stored in your password store, showing the folder structure and password names. pass organizes passwords into a folder structure that mirrors the structure of the passwords. If you've organized your passwords into folders based on categories or purposes, this command will give you an overview of the entire structure. |
rm [--recursive|-r] password/path |
Remove password/path [if it is a path to a directory, [--recursive|-r] removes it recursively. |
init gpg_key_id [--path=sub-folder] |
Initialize new password storage and use GPG ID public key for encryption. [Organize it in the sub-folder directory]. This command initializes the password store for a specific GPG key, but it doesn't automatically create any password entries. To add passwords to the store, you need to use the pass insert command. |
insert meaningful/path/to/stored/password |
Add passwords and organize with the following structure within $PASSWORD_STORE_DIR : meaningful/path/to/stored/password . The pass command uses the GPG public key specified during the initialization of the password store (that is, pass init . |
show meaningful/path/to/stored/password |
Uses the GPG private key associated with the password identity used during the initialization to decrypt and print the stored password. In other words, it will display the password saved in the encrypted entry password , which is located at $PASSWORD_STORE_DIR/meaningful/path/to/stored/ . |
ldd /path/to/your/executable |
Print shared object dependencies of executable . |
ldconfig |
Updates the default library search paths. |
-v|-p |
Print the default library search paths. |
ps |
Print a snapshot of the current processes |
-A|-e |
All. |
-H |
Show process tree hierarchy. |
-L |
Show LWP (Lightweight Process) and NLWP (Number of Lightweight Processes). An LWP is a thread, which is a basic unit of CPU utilization. In a traditional sense, a process consists of one or more threads, and each thread has its own LWP. Threads within the same process share resources like memory space but have their own execution contexts, allowing for parallel execution. NLWP represents the total number of LWPs (threads) in a process. It indicates how many threads are currently running within a specific process. |
-f |
Full-format listing, such as parend PID (PPID), etc... |
top |
Dynamic ps . |
jobs |
Display the status of processes that are running in the background (which are called jobs) owned by current shell session. |
fg %n |
Bring the n th job to foreground. |
ctrl+Z |
If a process hangs the terminal, you can press ctrl+Z to send a suspend signal to this precess. In this case, the suspended process becomes a job in suspended state |
ctrl+C |
If a process hangs the terminal, you can press ctrl+C to send a kill signal to this precess. |
bg %n |
Change the stato of the n th job to running status. |
disown %n |
Disown the n th background job from the current shell. It won't be list by the `jobs` command anymore However, the PPID (parent process ID) of the disowned process is still the PID of your terminal. When you kill your current terminal, the PPID of the child process chages. Note that, although the child process generally dies when you kill its parent process (it actually depends on how the parent process propagates the KILL signal), in this case, the PPID just changes (in the Unix jargon, we say that this child process was adopted by another process). |
systemctl |
Command-line utility used to control the systemd system and service manager. systemd is a system and service manager for Linux, which is widely adopted by modern Linux distributions. Besides some subtle differences in their historical and conceptual origins, the terms "services" and "daemons" are often used interchangeably. A service refers to a background process that runs continuously and provides specific functions to the operating system or other applications. Services are typically managed by a service management system, such as systemd on many modern Linux distributions. It's important to note that while all daemons are processes, not all processes are daemons. Regular foreground processes, such as those initiated by user commands in a terminal, are distinct from background services or daemons. |
list-units |