$ bash cheat sheet

Bash cheat sheet

setup
# Save credentials
git config --global credential.helper store

# Clone repository
git clone https://platform.zone01.gr/git/username/piscine-go.git

Quick reference

everyday commands

commanddescription
manhelp
lslist folders
cpcopy — cp source_file destination_file
mkdircreate directory
cdchange directory
mvmove directory
rmremove directory

display files

commanddescription
catconcatenate
lesspager
headbeginning of file
tailend of file

look at files

commanddescription
wcword count (-w word, -l line, -m char)
grepfilter matching text
findsearch for files
locatesearch for file names (fast)

whoami → USERNAME

Create directories

mkdir foo                          # Create a directory
mkdir foo bar                      # Create multiple directories
mkdir -p foo/bar                   # Create nested directory (--parents)
mkdir -p|--parents {foo,bar}/baz   # Create multiple nested directories
mktemp -d|--directory              # Create a temporary directory
cp --recursive foo bar             # Copy directory
mv foo bar                         # Move directory

Δημιουργία αρχείων: touch foo.txt, touch {foo,bar}.txt, touch test{1..3}, touch test{a..c} — δείτε αναλυτικά στο επόμενο section.

Delete directories

rmdir foo                          # Delete empty directory
rm -r|--recursive foo              # Delete directory including contents
rm -r|--recursive -f|--force foo   # Delete directory including contents, ignore nonexistent files and never prompt

Create files

touch foo.txt            # Create file or update existing file's modified timestamp
touch foo.txt bar.txt    # Create multiple files
touch {foo,bar}.txt      # Create multiple files
touch test{1..3}         # Create test1, test2 and test3 files
touch test{a..c}         # Create testa, testb and testc files

Άνοιγμα αρχείου στο VS Code: code foo.sh

Standard output, error and input

echo "foo" > bar.txt        # Overwrite file with content
echo "foo" >> bar.txt       # Append to file with content
ls exists 1> stdout.txt     # Redirect the standard output to a file
ls noexist 2> stderror.txt  # Redirect the standard error output to a file
ls 2>&1 > out.txt           # Redirect standard output and error to a file
ls > /dev/null              # Discard standard output and error
read foo                    # Read from standard input and write to the variable foo

Reading files

cat foo.txt    # Print all contents of a file (view file)
less foo.txt   # Print some contents at a time (g = top, SHIFT+g = bottom, /foo = search for 'foo')
head foo.txt   # Print top 10 lines of file
tail foo.txt   # Print bottom 10 lines of file
open foo.txt   # Open file in the default editor
wc foo.txt     # List number of lines, words and characters in the file

File permissions

ls -l /foo.sh              # List file permissions
chmod +100 foo.sh          # Add 1 to the user permission
chmod -100 foo.sh          # Subtract 1 from the user permission
chmod u+x foo.sh           # Give the user execute permission
chmod g+x foo.sh           # Give the group execute permission
chmod u-x,g-x foo.sh       # Take away the user and group execute permission
chmod u+x,g+x,o+x foo.sh   # Give everybody execute permission
chmod a+x foo.sh           # Give everybody execute permission
chmod +x foo.sh            # Give everybody execute permission

Find files

find /path -name foo.txt              # Find a file
find -iname foo.txt                   # Find a file with case insensitive search
find -name "*.txt"                    # Find all text files
find -name foo.txt -delete            # Find a file and delete it
find -name "*.png" -exec pngquant {}  # Find all .png files and execute pngquant on them
find -type f -name foo.txt            # Find a file
find -type d -name foo                # Find a directory
find -type l -name foo.txt            # Find a symbolic link
find -type f -mtime +30               # Find files that haven't been modified in 30 days
find -type f -mtime +30 -delete       # Delete files that haven't been modified in 30 days
find . -name "*.txt" -print0          # Αναζητά αρχεία και εκτυπώνει τα ονόματά τους διαχωρισμένα
                                       # με null byte αντί για αλλαγή γραμμής

Find in files — grep

grep = Global Regular Expression Print

grep 'foo' /bar.txt                          # Search for 'foo' in file 'bar.txt'
grep 'foo' /bar -r|--recursive               # Search for 'foo' in directory 'bar'
grep 'foo' /bar -R|--dereference-recursive   # Search in 'bar' and follow symbolic links
grep 'foo' /bar -l|--files-with-matches      # Show only files that match
grep 'foo' /bar -L|--files-without-match     # Show only files that don't match
grep 'Foo' /bar -i|--ignore-case             # Case insensitive search
grep 'foo' /bar -x|--line-regexp             # Match the entire line
grep 'foo' /bar -C|--context 1               # Add N lines of context above/below match
grep 'foo' /bar -v|--invert-match            # Show only lines that don't match
grep 'foo' /bar -c|--count                   # Count the number of lines that match
grep 'foo' /bar -n|--line-number             # Add line numbers
grep 'foo' /bar --colour                     # Add colour to output
grep 'foo\|bar' /baz -R                      # Search for 'foo' or 'bar' in directory 'baz'
grep --extended-regexp|-E 'foo|bar' /baz -R  # Use regular expressions
egrep 'foo|bar' /baz -R                      # Use regular expressions

grep -Z / grep --null   # Εκτυπώνει το όνομα του αρχείου που βρέθηκε ακολουθούμενο από null byte,
                         # ώστε άλλες εντολές να ξέρουν πού τελειώνει το ένα όνομα και πού αρχίζει το άλλο

Advanced παράδειγμα — αλλαγή σε filenames της λέξης palio σε neo:

find . -name "*.txt" -print0 | xargs -0 grep -lZ "palio" | xargs -0 sed -i 's/palio/neo/g'

Curl

curl https://example.com                    # prints the content of the URL
curl http://site.{one,two,three}.com        # multiple URLs: site.one.com, site.two.com, site.three.com
curl ftp://ftp.example.com/file[1-20].jpeg  # numeric sequence 1 to 20
curl -s|--silent https://example.com        # without progress bar
curl -# https://example.com                 # shows a simple progress bar

Cut

cut -d "c" -f1      # use 'c' as delimiter and get field (-f1 or -f2)
cut -f<n>          # get the nth field
cut -f<n-m>        # get fields nth to mth
cut -d " " -f 1,2   # using space as delimiter, extract fields 1 and 2
cut -c 2,5,7        # extract the characters at positions 2, 5, and 7 from each line

tr (replace)

echo "hello" | tr 'l' '1'      # replaces l with 1 → he11o
echo "aaabbbccc" | tr -s 'a'   # συμπίεση χαρακτήρων → abbbccc

Η tr δεν δέχεται απευθείας ονόματα αρχείων, αλλά λειτουργεί με ανακατεύθυνση (π.χ. tr 'a' 'b' < input.txt).

Replace in files — sed

sed 's/fox/bear/g' foo.txt              # (s = substitute) replace fox with bear in foo.txt
sed 's|fox|bear|g'                      # χρήση pipe ως delimiter
sed 's:fox:bear:g'                      # χρήση άνω-κάτω τελείας ως delimiter
sed 's#fox#bear#g'                      # χρήση hashtag ως delimiter

sed 's/fox/bear/gi' foo.txt             # replace fox (case insensitive) with bear
sed 's/red fox/blue bear/g' foo.txt     # replace red with blue and fox with bear
sed 's/fox/bear/g' foo.txt > bar.txt    # replace and save the result to bar.txt
sed 's/fox/bear/g' foo.txt -i|--in-place  # replace and overwrite foo.txt

sed -e 's/apple/orange/' -e 's/cat/dog/' file.txt   # multiple replacements with -e
sed -n 's/apple/orange/p' file.txt      # print only lines that matched (-n silent + p print)
sed -i 's/apple/orange/' file.txt       # modify the file directly (-i.bak keeps a backup)
sed -f my_script.sed file.txt           # read the replacements from a script file
sed -z 's/\n/ /g'                       # lines split by null byte (\0) instead of \n —
                                         # often used with `find -print0` or `grep -Z`

Βάζω μονά ' εισαγωγικά στο 95% των περιπτώσεων, διπλά " όταν έχω variables (ή τον χαρακτήρα ' μέσα στο πεδίο, π.χ. don't). Με διπλά " το τερματικό "διαβάζει" το περιεχόμενο πριν το στείλει στο sed.

Εντολές (sed)

sed '/fox/d'                    # (delete) διαγράφει όλες τις γραμμές που περιέχουν fox
sed '3d'                        # διαγράφει μόνο την 3η γραμμή
sed '/^$/d'                     # διαγράφει όλες τις κενές γραμμές
sed '/fox/i NewText'            # (insert) νέα γραμμή πριν από κάθε γραμμή με fox
sed '/fox/a NewText'            # (append) νέα γραμμή μετά από κάθε γραμμή με fox
sed '/fox/c This is replaced'   # (change) αντικαθιστά ολόκληρη τη γραμμή που έχει fox
sed 'y/abc/ABC/' foo.txt        # (transform) αντιστοιχίζει χαρακτήρα προς χαρακτήρα, σαν tr

Flags (sed)

Το g στο τέλος είναι flag και ορίζει πώς θα γίνει η αντικατάσταση στη γραμμή.

flagσημασία
(κανένα)Αντικαθιστά μόνο την πρώτη εμφάνιση στη γραμμή
g (global)Αντικαθιστά όλες τις εμφανίσεις στη γραμμή
αριθμός, π.χ. 2Αντικαθιστά μόνο τη συγκεκριμένη εμφάνιση, π.χ. sed 's/fox/bear/2'
i (ignore case)Αναζήτηση χωρίς διάκριση πεζών/κεφαλαίων
pΤυπώνει τη γραμμή αν η αντικατάσταση πέτυχε (συχνά με sed -n ... p)
w file.txtΓράφει το αποτέλεσμα σε νέο αρχείο

jq

Σαν sed για JSON δεδομένα — εξωτερικό library.

jq '.'                        # pretty-prints ολόκληρο το JSON
jq '.foo'                     # τιμή του κλειδιού "foo" στο root object
jq '.["foo"]'                 # εναλλακτικό syntax για keys με ειδικούς χαρακτήρες/κενά
jq '.user.profile.id'         # πρόσβαση σε nested fields

jq --raw-output | -r          # raw strings χωρίς εισαγωγικά (για shell variables)
jq --raw-output0              # raw strings, τυπώνει NUL αντί για newline μετά από κάθε output

jq '.items[0]'                # πρώτο στοιχείο ενός array
jq '.items[]'                 # iterate πάνω σε array, κάθε στοιχείο ξεχωριστό output
jq '.items[].name'            # πεδίο "name" από κάθε object μέσα σε array

jq -c | --compact-output      # minify output, ένα object ανά γραμμή
jq -s | --slurp                # διαβάζει πολλά JSON objects σε ένα μεγάλο array
jq -S | --sort-keys           # αλφαβητική ταξινόμηση των keys
jq 'keys'                     # array με όλα τα keys του object
jq 'length'                   # πλήθος στοιχείων array ή χαρακτήρων string

jq '[.id, .name]'                             # μετατροπή πεδίων σε νέο array
jq '.[] | select(.id == 100)'                 # φιλτράρισμα όπου "id" == 100
jq '.[] | select(.name | contains("test"))'   # φιλτράρισμα όπου "name" περιέχει "test"
jq 'map(.price * 1.25)'                       # υπολογισμός (π.χ. 25% φόρος) σε κάθε στοιχείο

Advanced logic

jq 'if .status == 200 then "Success" else "Fail" end'   # conditional logic
jq '.optional_field // "N/A"'                            # default τιμή αν είναι null/missing
jq 'try .id catch "error"'                                # αποφυγή crash σε access error
jq '.tags | join(", ")'                                   # συνδυασμός στοιχείων σε string

Pipe chain

Για να συνδυάσεις πολλές εντολές, χρησιμοποιείς το pipe | μέσα στα εισαγωγικά — το αποτέλεσμα του αριστερού φίλτρου περνάει ως είσοδος στο δεξί.

jq '.items[] | try .id catch "N/A" | select(. != "N/A")'
# προσπαθεί να πάρει τα IDs, αντικαθιστά errors με "N/A", και φιλτράρει τα "N/A"

jq '.data[] | {user: .name, score: .points} | select(.score > 50)'
# δημιουργεί νέο object με μετονομασμένα keys, μετά φιλτράρει με βάση το νέο "score"

jq 'map(try .price catch 0) | add'
# προσπαθεί να πάρει όλες τις τιμές (0 σε errors) και τις αθροίζει

user_id=$(curl -s "https://api.example.com/user" | jq -r '.id')
# αποθηκεύει μια τιμή JSON σε shell variable με το -r (raw) flag

curl -s "https://api.github.com/users/octocat/repos" | jq -c '.[] | {name, stars: .stargazers_count}'
# φέρνει όλα τα repos και τυπώνει minified λίστα με name + star count

Useful chaining patterns

jq 'del(.unused_field) | .updated_at = "2026-02-02"'
# αφαιρεί ένα field και προσθέτει/ενημερώνει ένα άλλο στο ίδιο flow

jq '.[] | select(.status == "active") | .email' | tr 'A-Z' 'a-z'
# συνδυάζει jq με tr για emails σε lowercase

jq '.results | length as $len | .[] | {total: $len, item: .name}'
# αποθηκεύει το μήκος του array σε μεταβλητή ($len) για να το χρησιμοποιήσει σε κάθε item

Key rule for chaining: όταν χρησιμοποιείς | μέσα στο jq '...', σκέψου το σαν γραμμή παραγωγής — κάθε κομμάτι φιλτράρει ή αλλάζει τα δεδομένα και τα δίνει στο επόμενο.

Running & customizing

edit ~/.bashrc to run ls after cd

# Always run ls after cd
function cd {
  builtin cd "$@" && ls
}

run a bash script (.sh)

chmod +x /path/to/yourscript.sh   # give everybody execute permission
bash /path/to/yourscript.sh

#!/bin/bash λέει στο λειτουργικό σύστημα να χρησιμοποιήσει bash ως command interpreter.

Bash scripts

variables

#!/bin/bash

foo=123                 # Initialize variable foo with 123
declare -i foo=123      # Initialize an integer foo with 123
declare -r foo=123      # Initialize readonly variable foo with 123
echo $foo               # Print variable foo
echo ${foo}_'bar'       # Print variable foo followed by _bar
echo ${foo:-'default'}  # Print variable foo if it exists, otherwise print default

export foo               # Make foo available to child processes
unset foo                # Make foo unavailable to child processes

Παράδειγμα configure env. variable: export PATH="$PATH:/my/path"

environment variables

#!/bin/bash

env             # List all environment variables
echo $PATH      # Print PATH environment variable
export FOO=Bar  # Set an environment variable

functions

#!/bin/bash

greet() {
  local world = "World"
  echo "$1 $world"
  return "$1 $world"
}

greet "Hello"
greeting=$(greet "Hello")

exit codes

#!/bin/bash

exit 0   # Exit the script successfully
exit 1   # Exit the script unsuccessfully
echo $?  # Print the last exit code

if statements

#!/bin/bash

if [[$foo = 'bar']]; then
  echo 'one'
elif [[$foo = 'bar']] || [[$foo = 'baz']]; then
  echo 'two'
elif [[$foo = 'ban']] && [[$USER = 'bat']]; then
  echo 'three'
else
  echo 'four'
fi

inline if statements

#!/bin/bash

[[ $USER = 'zone01' ]] && echo 'yes' || echo 'no'

while loops

#!/bin/bash

declare -i counter
counter=10
while [$counter -gt 2]; do
  echo The counter is $counter
  counter=counter-1
done

for loops

#!/bin/bash

for i in {0..10..2}
  do
    echo "Index: $i"
  done

for filename in file1 file2 file3
  do
    echo "Content: " >> $filename
  done

for filename in *;
  do
    echo "Content: " >> $filename
  done

case statements

#!/bin/bash

echo "What's the weather like tomorrow?"
read weather

case $weather in
  sunny | warm ) echo "Nice weather: " $weather
  ;;
  cloudy | cool ) echo "Not bad weather: " $weather
  ;;
  rainy | cold ) echo "Terrible weather: " $weather
  ;;
  * ) echo "Don't understand"
  ;;
esac

Regular expressions

patternmeaning
\escape the next character, e.g. \^ matches "^" and not "start of line"
^start of line
$match end of line
[ ]match any character in brackets, e.g. [abc] matches a, b or c
-match a range, e.g. [0-9] matches numbers 0 to 9
[^ ]match all except listed in brackets, e.g. [^0-9] matches everything except numbers
.single character of any value
*zero or more characters of any value
Aupper case A
alowercase a
\dany single digit
\Dany single non-digit character
\wany alphanumeric character