It’s the place where I write down somewhat useful syntax snippets. Instead of keeping my local copy I decided to make it public. Maybe it’s helpful for someone. Most probably that will be myself when I’m not near the local copy.

Hall of Syntax:

  1. bash stuff
  2. miscellanous
  3. syntax mess
  4. git stuff
  5. synology stuff
  6. vim stuff

bash stuff

source and export

Source and export are fundamental when you need to use other scripts or to be sure that child processes have see the variables they need:

#!/bin/bash

# source executes a script in the context of the calling shell
source script.sh
# source can be called by a single dot
. script.sh
# not to be confused with a dot at the beginning of a path which means "current directory"
. ./dir1/script.sh
# not to be confused with a dot at the beginning of a filename which indicates a hidden file
. ./dir1/.script.sh

# settings variables makes them available in the current process only
FOO="HELLO WORLD"
# any child process won't see $FOO

# exported variables get passed on to child processes, non-exported variables do not
export FOO="HELLO WORLD"
# any child process now will see $FOO

unset FOO

arguments

The snippets below show how to use arguments inside a script:

#!/bin/bash

echo  "number of arguments     :"  $#
echo  "programname             :"  $0
echo  "1st argument            :"  $1
echo  "2nd argument            :"  $2
echo  "all arguments           :"  $*
echo  "each argument in quotes :"  "$@"
echo  "last return value       :"  $?

redirections and piping

The snippets below show how to use redirections and piping:

#!/bin/bash

make 1> log.txt 2> error.txt    # redirect std output to log.txt and error to error.txt
make > log.txt 2> error.txt     # same as above
make >> log.txt 2>> error.txt   # same as above but appending instead overwriting
make &> log.txt                 # redirect std output and error to log.txt
make 2>&1 | tee log.txt         # redirect std error to standard output, then pipe to tee
make 2>error.txt | hexdump -C   # pipe std output but redirect error to file
hexdump -C < log.txt            # redirect std input

conditional expressions

#!/bin/bash

# compile hello.c and run the program if compilation was successful
gcc hello.c -o hello && ./hello
# compile hello.c and print hello.c if compilation was not successful
gcc hello.c -o hello || cat hello.c
# combine both: run on success but print on failure
gcc hello.c -o hello && ./hello || cat hello.c

# execute 'ls' if argument 1 equals 1
test $1 -eq 1 && ls

# same as above
[ $1 -eq 1 ] && ls

# strings
s1="abcdef"
s2="xyz"
if [ "$s1" =  "$s2" ];   then echo "strings are equal";     else echo "strings are not equal"; fi
if [ "$s1" != "$s2" ];   then echo "strings are not equal"; else echo "strings are equal"; fi
if [ "$s1" \<  "$s2" ];  then echo "s1 is smaller";         else echo "s1 is not smaller"; fi
if [ "$s1" \>  "$s2" ];  then echo "s1 is bigger";          else echo "s1 is not bigger"; fi
if [ -z "$s1" ]; then echo "string has zero length"; fi
if [ -n "$s1" ]; then echo "string has not zero length"; fi

# comparing numbers
if [ x -eq y ]; then echo "equal"; fi
if [ x -ne y ]; then echo "not equal"; fi
if [ x -lt y ]; then echo "less than"; fi
if [ x -gt y ]; then echo "greater than"; fi
if [ x -le y ]; then echo "less or equal"; fi
if [ x -ge y ]; then echo "greater or equal"; fi

# expressions for testing
if [ -d $1 ]; then echo "first argument is a directory"; fi
if [ -f $1 ]; then echo "first argument is an ordinary file"; fi
if [ -e $1 ]; then echo "first argument is an existing file"; fi
if [ -r $1 ]; then echo "first argument is readable"; fi
if [ -s $1 ]; then echo "first argument is a file with more than zero bytes"; fi
if [ -w $1 ]; then echo "first argument is writable"; fi
if [ -x $1 ]; then echo "first argument is executable"; fi
if [ -n $1 ]; then echo "first argument (string) is larger than zero"; fi
if [ -z $1 ]; then echo "first argument (string) has zero length"; fi
if [ -o $1 ]; then echo "first argument (option) is active"; fi
if [ file1 -nt file2 ]; then echo "file1 is newer than file2"; fi
if [ file1 -ot file2 ]; then echo "file1 is older than file2"; fi

# conjunction: -a
if [ $x -eq 1 -a $y -lt 10 ]; then echo "true"; else echo "false"; fi

# disjunction: -o
if [ $x -eq 1 -o $y -lt 10 ]; then echo "true"; else echo "false"; fi

# not: !
if [ ! -f $1 ]; then echo "true"; else echo "false"; fi

# using grep for conditional expressions
if grep -q keyword $file
then
  echo "keyword found"
else
  echo "keyword not found"
fi

# check second argument for value 's', 'c' or 'h'
case $2 in
s) echo "SHOW IT"
   cat $1;;
c) echo "COMPILE IT"
   gcc $1;;
h) echo "HEXDUMP IT"
   hexdump -C $1;;
*) echo "DO NOTHING";;
esac

loops

#!/bin/bash

# for loop that lists all arguments line by line
for i in $*; do
  echo $i
done

# shortcut for the loop above
for i; do
  echo $i
done

# list all arguments with index like "argument 3: ..."
j=1
for i in $*; do
  echo "argument $j:" $i
  ((j++))
done

# same behaviour as the loop above
for (( i=1; i<$#+1; i++ ))
do
  echo "argument" $i":" ${!i}
done

# example: ping hosts that are listed in server.txt (separated by space or line break)
for i in `cat server.txt`
do
  echo -e -n $i "\t-> "
  ping -c 1 $i | grep "ttl=" 
done

# alternative for above using while and read
while read f
do
  echo -e -n $f "\t-> "
  ping -c 1 $f | grep "ttl="
done < server.txt

while read f
do
done < server.txt

# while loop: loop while val is not 1 and not 2
val=0
while test $val != 1 && test $val != 2
do
  echo -n "enter val (must be 1 or 2) > "
  read val
done

# until loop: loop until val is 3
val=0
until test $val = 3
do
  echo -n "enter val (must be 3) > "
  read val
done

# parse file line by line and do action for each line
while read -r line; do COMMAND $line; done < x.txt

# Example for above: Open each line as URL with Firefox on macOS
while read -r line; do Open /Applications/Firefox.app/ -u "$line"; done < x.txt

using functions in bash:

#!/bin/bash

# foo prints the sum of its numerical arguments
foo()
{
  sum=0
  for i; do sum=$[ sum + $i ]; done
  echo "The sum of $* is" $sum
}

bar()
{
  echo "This is bar. I don't use arguments."
}

foo 100 5 200
bar 100 5 200

some quite useful command syntax

# show third field of each line in test.txt with delimiter '#'
cut -d# -f3 test.txt

# print the second word of each line in test.txt
awk '{ print $2 }' test.txt

# calculate something near to PI
echo "scale=5; 22/7" | bc

# replace string "auss" with "inn"
sed s/auss/inn/g test.txt

# same as above plus overwrite file with result and store backup with extension ".backup"
sed -i .backup s/auss/inn/g test.txt

# replace string in all files, recursively
find . -type f -exec sed -i 's/foo/bar/g' {} +

# ...above on macOS
find . -type f -exec sed -i '' -e 's/PROXIMITY/DISTANZ/g' {} +

# archive all files and folders beginning with a dot
tar cvf archive.tar .[^.]*

miscellanous

Matlab: Manually plot connected dots

This Matlab script draws and connects single points which are given by the array with the variable name points. The image to the right shows the result of the script below. The script checks the size of the array points with the size() function and assigns the returned value – which is (8, 2) in the example below – to the variable x. That means we have an array with 8 times 2 values. Later, x is used by the for-loop to get the amount of points with x(1) which returns 8. Before doing the actual task, a horizontal and a vertical black line is plotted to indicate the abscissa and the ordinate. Then the script draws a filled circle for each point and then plots a line to the next point. draw connected points with Matlab

hold off

% set points to draw and connect
points = [ 0 0;  5 5;  10 5;  11 10; 15 5; 15 15; 5 15; 0 0];

% get amount of points in array points
x = size(points);
amount = x(1);

% plot the axes to the plot explicitly
plot([0 0], [-5 20], 'k-')
hold on
grid on
plot([-5 20], [0 0], 'k-')

% draw each point and a line to the next point
for i = 0:x(1)-1
    scatter(points(i+1,1),points(i+1,2),50,'blue','filled')
    plot([points(i+1,1) points(i+2,1)], [points(i+1,2) points(i+2,2)], 'blue-')
end
scatter(points(i+1,1),points(i+1,2),50,'blue','filled')

hold off

OS X: bash script toggling visibility of hidden files in Finder

toggle hidden files visibility in OS X Finder

if [ "$1" == "ON" ];then
echo "Setting Finder to show hidden files"
defaults write com.apple.finder AppleShowAllFiles TRUE;killall Finder
else
    if [ "$1" == "OFF" ];then
    echo "Setting Finder to NOT show hidden files"
    defaults write com.apple.finder AppleShowAllFiles FALSE;killall Finder
    else
        echo "Give me parameter ON or OFF"
    fi
fi

OS X: bash script toggling the OS X dashboard

kill or enable the OS X dashboard

if [ "$1" == "ON" ];then
echo "Enabling dashboard..."
defaults write com.apple.dashboard mcx-disabled -boolean NO && killall Dock
else
    if [ "$1" == "OFF" ];then
    echo "Killing dashboard..."
    defaults write com.apple.dashboard mcx-disabled -boolean YES && killall Dock
    else
        echo "Give me parameter ON or OFF"
    fi
fi

editing DNS Records

General Syntax: [DOMAIN/SUBDOMAIN] [TYPE] [VALUE]

TYPE        DESCRIPTION
--------------------------
A           point to IPv4
AAAA        point to IPv6
CNAME       redirect to another domain or subdomain

examples:
website.com       A       1.2.3.4
www.website.com   CNAME   website.com
blog.website.com  CNAME   website.com
ftp.website.com   CNAME   website.com
*.website.com     CNAME   website.com
pi.snej.de        CNAME   snej.mygreatdnsservice.com

Raspberry Pi Camera code snippets

take photos

while [ 1 ]
do
    uname -a > cam.txt
    echo -n `date` "uptime=" >> cam.txt
    echo `uptime` | cut -b13- >> cam.txt
    echo -n "soc_core_" >> cam.txt
    /opt/vc/bin/vcgencmd measure_temp >> cam.txt
    raspistill -t 0 -n -q 20 -ex night -rot 270 -w 1024 -h 768 -o cam_new.jpg
    convert -pointsize 20 -fill yellow -draw 'text 10,20 "@cam.txt"' cam_new.jpg cam_new.jpg
    mv cam_new.jpg cam.jpg
    convert cam.jpg -resize 50% -quality 50 "snapshots/cam_`date +%Y-%m-%d_%H-%M-%S`.jpg"
    sleep 6
done

rename photos

for file in *.JPG ; do mv "${file}" "${file%.JPG}_suffix.JPG";  done
i=1;
for file in cam_*.JPG ; do mv -v "${file}" "$i.jpeg"; i=$[i+1]; done

create video from photos

~/bin/ffmpeg -r 20 -i %d.jpeg /Users/jens/Desktop/vid.mp4

concat video files

ffmpeg -v info -f concat -i files.txt  -c copy output.mp4
with files.txt containing:
    file '2017_0515_010105_001.MP4'
    file '2017_0515_011328_002.MP4'

convert to h264

ffmpeg -i input.mp4 -vcodec h264 output.mp4

cut video file

ffmpeg -i input_video.mp4 -ss 00:02:15 -to 00:05:30 -c copy      output_video.mp4    # cut before 2:15 and after 5:30
ffmpeg -i input.mkv       -ss 00:00:00  -t 00:30:00 -codec copy  out.mkv             # cut after 30 minutes

syntax mess

Here you’ll see a mess of syntax snippets that I found useful at some point in my life. Since this category is called ‘mess’ there is no particular order or useful description. Continue reading at your own risk!

# python - debug step by step, beginning from certain location in code
import pdb
pdb.set_trace()

gsettings set org.gnome.shell.extensions.ding show-trash false
gsettings set org.gnome.shell.extensions.ding show-home false

setterm -blength 0
xset b off

##
## public DNS servers
##
Provider                Primary DNS Server  Secondary DNS Server
Level31                 209.244.0.3         209.244.0.4
Google2                 8.8.8.8             8.8.4.4
Comodo Secure DNS       8.26.56.26          8.20.247.20
OpenDNS Home3           208.67.222.222      208.67.220.220
DNS Advantage           156.154.70.1        156.154.71.1
Norton ConnectSafe4     199.85.126.10       199.85.127.10
GreenTeamDNS5           81.218.119.11       209.88.198.133
SafeDNS6                195.46.39.39        195.46.39.40
OpenNIC7                216.87.84.211       23.90.4.6
Public-Root8            199.5.157.131       208.71.35.137
SmartViper              208.76.50.50        208.76.51.51
Dyn                     216.146.35.35       216.146.36.36
censurfridns.dk9        89.233.43.71        89.104.194.142
Hurricane Electric10    74.82.42.42  
puntCAT11               109.69.8.51  

# 99 bottles of lisp
(labels ((foo (x)
   (and (<= 0 x) (cons x (foo (1- x))))))
   (format t (format nil 
        "~~{~~&~~@(~~%~~R ~A ~A!~~)~~:*~~&~~@(~~R
~0@*~A!~~)~~&~~@(~2@*~A!~~)~~&~~@(~~[~A~~:;~~:*~~R~~:*~~] ~0@*~A!~~)~~}"
        "bottles of beer"
        "on the wall"
        "take one down, pass it around" 
        "no more"
        )
 (foo 99)))

for i in `ls *.jpg`; do convert -resize 50% -quality 90 $i conv_$i; done 

# crop all files and then... do some more things
for i in `ls *.png`; do convert -verbose -crop 1352x970+985+219 $i 123/conv_$i; done
i=0; while [ $i -lt 10 ]; do echo "mv seite_$i"; i=$[i+1]; done
for name in *\ *; do echo \"$name\"; done

# file permissions
r            read.
w            write.
x            execute or access for directories.
X            execute only if the file is a directory or already has
             execute permission  for  some user.
s            set user or group ID on execution.
t            sticky.
u            the permissions granted to the user who owns the file.
g            the permissions granted to the file’s group.
o            and the permissions granted to users that are not u or g.




openssl aes-256-cbc -e -a -in PLAIN -out ENCRYPTED
openssl aes-256-cbc -d -a -in ENCRYPTED -out PLAIN

git tag -a v1.0
git tag -a v0.9 558151a
git log –oneline –decorate –graph



alias english=’export LANG=en_US’

duck -e overwrite --password mylittlepony --upload sftp://ponyguy@server.com/path aLocalDir

# you may add --user foo --password bar
wget \
 --recursive \
 --no-clobber \
 --page-requisites \
 --html-extension \
 --convert-links \
 --restrict-file-names=windows \
 --domains snej.de \
 --no-parent \
http://snej.de/

sed -i.bak 's/OLDSTRING/NEWSTRING/g' *.cpp

echo "A;B:C,D.E" | awk -F'[,;.:]' '{print $3}'

# adding --delete to rsync will remove files from micro128 which are not existing in Documents
rsync -ravzh Documents /Volumes/micro128/

pandoc --number-sections -t html | pandoc -f html -t markdown 

NRF51 Programming: Target BOOT

"The book promotes a clean, side-effect-free style of programming for the first eight chapters. Chapter 9 discusses i/o."

# git diff of a certain file between head and a certain tag
git diff HEAD COOL_TAG -- path/to/file.c

# decrypt encrypted PDFs
qpdf --password=12345 --decrypt pdf-mit-pw.pdf pdf-ohne-pw.pdf
find . -iname "*.pdf" | xargs -t -I {} echo qpdf --password=12345 --decrypt {} {}-decrypted.pdf

# find all files named *.bin and zip them
find . -iname "*.bin" | xargs -t -I {} 7z a -- {}.zip {}

# rotate video
ffmpeg -i in.mov -vf "transpose=1" out.mov
  0 = 90CounterCLockwise and Vertical Flip (default)
  1 = 90Clockwise
  2 = 90CounterClockwise
  3 = 90Clockwise and Vertical Flip
  Use -vf "transpose=2,transpose=2" for 180 degrees.
  copy the audio without touching it, by using -c:a copy

git stuff

undo

git reset HEAD~                  # undo last commit
git reset HEAD~N                 # undo last N commits
git reset --soft HEAD~           # undo last commit and keep staged stuff
git reset --hard HEAD~           # undo last commit and discard changes
git gc --prune=now --aggressive  # force git to run garbage collector

rebase your branch to latest master on origin

git checkout master
git pull
git checkout -                   # goes back to your branch
git rebase master
git push --force

squash

All squash examples below will squash the last 5 commits

via merge

git reset --hard HEAD~5          # git back 5 commits 
git merge --squash HEAD@{1}      # squash from here to HEAD
git commit                       # editor will come up with all commit messages

via reset

git reset --soft HEAD~5 && git commit   # editor will come with empty commit message

via interactive rebase

git rebase -i HEAD~5             # then select s (squash) for the commits to squash

amend multiple commits

git rebase -i HEAD~5             # then select e (edit) for the commits to amend
                                 # then call git commit --amend && git rebase --continue
                                 # ...until all commits have been amended

Checkout master from origin

git checkout -B master origin/master

Pull without auto-merge

git pull --rebase

Stage hunks interactively

git add -p <filename>

delete remote tags & branches

git push --delete origin v1.0                  # deletes the a branch or tag named "v1.0"
git push --delete origin refs/tags/v1.0        # explicitly delete a tag (no confusion with branches)
git push --delete origin refs/heads/my/branch  # explicitly delete a branch (no confusion with tags)

change timestamp of last commit

newdate="Tue 30 Mar 2021 12:34:56 GMT"; GIT_COMMITTER_DATE=$newdate git commit --amend --no-edit --date "$newdate"

notes for my NAS (Synology DS218j)

ssh stuff

It’s not enough to copy your key to the authorized_keys file. Therefore:

# avoid indexing of your data
Control Pangel -> Indexing Service -> Media Indexing -> Indexed Folder -> remove all folders
Note: Data in your ~/Drive folder will still be index... just don't use the ~/Drive folder :-)

# enable ssh and rsync
Control Panel -> Terminal & SNMP -> Terminal -> Enable SSH servie
Control Panel -> File Services -> FTP -> Enable SFTP servie
Control Panel -> File Services -> rsync -> Enable rsync service
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 755 /volume1/homes/$USERNAME

# add this line in /etc/sshd/sshd_config:
RSAAuthentication yes

# uncomment this line in /etc/sshd/sshd_config:
PubkeyAuthentication yes

# restart
sudo synoservicectl --reload sshd

vim stuff

# delete until a certain line
:d167G         delete until line 167

# search (%=all lines; g=all occurenves in each line)
:%s/foo/bar/g  

# column mode
CTRL+SHIFT+V   y,d,…   SHIFT+i to insert text