# bash
echo \\\\\\
\\\
echo -e \\\\\\
\\
# ksh
echo \\\\\\
\\
--
jako konec přepínačů
echo -e
echo -e -e
echo -- -e
-- -e
echo -en '-e\n'
-e
FILE='my single file'
echo touch $FILE
touch my single file
touch $FILE
ls
file my single
printf -- "%s\n" "$var"
printf -v tmp -- "%s " "${var[@]}"
printf -- "%s\n" "${tmp% }"
IFS=" "
printf '%s\n' "$*"
Vytvoření a smazání souboru
#!/bin/bash
T=$(mktemp)
echo "$$"
exec >"$T"
rm "$T"
while sleep 5
do
date | tee /dev/stderr
done
ls -l /proc/11748/fd
total 0
lrwx------ 1 ... 0 -> /dev/pts/1
l-wx------ 1 ... 1 -> /tmp/tmp.6LrhtNEhda (deleted)
lrwx------ 1 ... 2 -> /dev/pts/1
lr-x------ 1 ... 255 -> /tmp/holder
Obnovení souboru
tail -n +1 -f /proc/_PID_/fd/1 >/tmp/recovery
Proč (ne)?
Obvyklý nástroj (neřeší žádný z důvodů): shc
#!/bin/bash
echo secretpassword | md5sum
Kompilace skriptu
shc -f secret.sh
ls -l secret.sh*
-rwxr-xr-x ... 42 ... secret.sh
-rwx--x--x ... 9560 ... secret.sh.x
-rw-r--r-- ... 9630 ... secret.sh.x.c
time for ((i=0;i<=1000;i++)); do ./secret.sh ; done >/dev/null
real 0m1.721s
user 0m0.104s
sys 0m0.148s
time for ((i=0;i<=1000;i++)); do ./secret.sh.x ; done >/dev/null
real 0m3.278s
user 0m0.040s
sys 0m0.228s
strings /proc/8910/cmdline
./secret.sh.x -c
_spousta_mezer_
£!/bin/bash
echo secretpassword | md5sum
./secret.sh.x
~/.bashrc, ~/.bash_profile, ...
--login, --init-file, --rcfile, --norc, --posix, ...
IFS, CDPATH, BASH_ENV, GLOBIGNORE, HIST*, LC_*, PATH, PROMPT_COMMAND, PS1..PS4, TMOUT, ...
braceexpand, history, noglob, noclobber, pipefail, posix, verbose, xtrace, vi/emacs, ...
cdspell, dotglob, execfail, expand_aliases, extglob, failglob, globstar, globasciiranges, interactive_comments, lastpipe, nocaseglob, nocasematch, nullglob, xpg_echo, ...
--noediting, $INPUTRC, ~/.inputrc, bind, read -e, ...
bash_completion, $COMP*, complete, ...
stdin
(např. telnet
, passwd
)?expect
- programmed dialogue with interactive programs
LC_ALL=C passwd <<EOF # GNU/Linux
> abc123
> xyz987
> xyz987
> EOF
Changing password for barinkl.
(current) UNIX password: Enter new UNIX password:
Retype new UNIX password: passwd: password updated
successfully
LC_ALL=C passwd <<EOF # Solaris 11
> abc123
> xyz987
> xyz987
> EOF
passwd: Changing password for barinkl
Enter existing login password:
#!/usr/bin/expect -f
# wrapper to make passwd(1) be non-interactive
# username is passed as 1st arg, passwd as 2nd
set password [lindex $argv 0]
set newpassword [lindex $argv 1]
spawn passwd
expect "assword:"
send "$password\r"
expect "assword:"
send "$newpassword\r"
expect "assword:"
send "$newpassword\r"
expect eof
./po abc123 xyz987
spawn passwd
Enter existing login password:
New Password:
Re-enter new Password:
passwd: password successfully changed for barinkl
expect -c '
spawn telnet www.google.com 80
send "GET / HTTP/1.0\n\n"
expect eof
'
#!/usr/bin/expect -f
spawn telnet www.google.com 80
send "GET / HTTP/1.0\n\n"
expect eof
send "string"
expect {
pattern { action }
pattern { action }
...
}
send "..."
expect { ... }
...
{ }
lze vynechat, v případě jediného nebo žádného vzoru/akce
Vzor je řetězec, který může obsahovat proměnné ($var
)
^, $, ., [ ], [^ ], *, ( | )
}^, $, ?, [ ], *
}
<employees>
<employee><firstName>John</firstName><lastName>Doe</lastName></employee>
<employee><firstName>Anna</firstName><lastName>Smith</lastName></employee>
<employee><firstName>Peter</firstName><lastName>Jones</lastName></employee>
</employees>
xmlstarlet sel -t -v '/employees/employee[1]/firstName' -n <xml
John
xmlstarlet sel -t -m '/employees/employee[1]/*' -v 'name()' -n <xml
firstName
lastName
xmlstarlet sel -t -v '/employees/employee/lastName' -n <xml
Doe
Smith
Jones
{"employees":[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName":"Jones"}
]}
jq '.employees[1].firstName' <json
"Anna"
jq '.employees[0] | keys' <json
[ "firstName", "lastName" ]
jq '.employees[].lastName' <json
"Doe"
"Smith"
"Jones"
inotify
- monitoring filesystem events
inotifywait
- wait for changes to files using inotify
-m, --monitor
-r, --recursive
-t seconds, --timeout seconds
-e event, --event event
--format fmt
inotifywait -mr .
Setting up watches. Beware: since -r
was given, this may take a while!
Watches established.
touch file ./ CREATE file
./ OPEN file
./ ATTRIB file
./ CLOSE_WRITE,CLOSE file
date > file ./ MODIFY file
./ OPEN file
./ MODIFY file
./ CLOSE_WRITE,CLOSE file
inotifywait -mr \
--format %w%f \
--event close_write \
--quiet \
. \
| (
IFS=$'\n'
while read
do
ls -i "$REPLY"
done
)
2228283 ./file
2228256 ./file2
2228299 ./file3
arr=(one two three)
declare -p arr
declare -a arr='([0]="one" [1]="two" [2]="three")'
( IFS=:; echo ${arr[*]} )
one two three
( IFS=:; echo "${arr[*]}" )
one:two:three
arr=(abc def [7]=ghi)
declare -p arr
declare -a arr='([0]="abc" [1]="def" [7]="ghi")'
for index in "${!arr[@]}"; do
new[$index]=${arr[$index]}
done
declare -p arr new
declare -a arr='([0]="abc" [1]="def" [7]="ghi")'
declare -a new='([0]="abc" [1]="def" [7]="ghi")'
arr=(abc def [7]=ghi)
declare -p arr
declare -a arr='([0]="abc" [1]="def" [7]="ghi")'
declare -p arr | sed 's/ arr=/ new=/'
declare -a new='([0]="abc" [1]="def" [7]="ghi")'
eval $(declare -p arr | sed 's/ arr=/ new=/')
declare -p arr new
declare -a arr='([0]="abc" [1]="def" [7]="ghi")'
declare -a new='([0]="abc" [1]="def" [7]="ghi")'
arr=(abc def [7]=ghi)
declare -p arr
declare -a arr='([0]="abc" [1]="def" [7]="ghi")'
new=("${arr[@]}")
declare -p arr new
declare -a arr='([0]="abc" [1]="def" [7]="ghi")'
declare -a new='([0]="abc" [1]="def" [2]="ghi")'
touch a b c d
(
ls a b foo c d xxx 2>&1 1>&3 \
| grep -cH '.' >&2
) 3>&1 | wc -l
(standard input):2
4
wc -L words
0.25 s
awk 'length>max {max=length} END {print max}' words
1.5 s
awk '{print length}' | sort -n | tail -1
3 s
tr -c '\n' . | sort -u | tail -1 | wc -c
len=$(wc -l < words); i=1
while [ "$i" -le "$len" ]; do
head -n "$i" words | tail -1 | wc -c
i=$(expr "$i" + 1)
done | sort -n | tail -1
loop1() { i=0; while [ $i -lt 1000 ]; do
echo $i; ((i++)); done; }
loop2() { i=0; while [ $i -lt 1000 ]; do
echo $i; i=`expr $i + 1`; done; }
time loop1
user: 0.140s | system: 0.008s | real: 0.151s
enable -n echo; time loop1
user: 2.756s | system: 2.344s | real: 3.529s
enable -n echo [ ; time loop1
user: 5.404s | system: 2.344s | real: 6.640s
enable -n echo [ ; time loop2
user: 7.568s | system: 4.596s | real: 10.678s
if ! LINE=$(
getopt -n "$0" \
-o lm:o:: \
-l long,mandatory:,optional:: \
-- "$@"
)
then
usage >&2
exit 2
fi
eval set -- "$LINE"
while [ $# -gt 0 ]
do
case $1 in
-l|--long) LONG=1; shift;;
-m|--mandatory) MANDATORY=$2; shift 2;;
-o|--optional) OPTIONAL=$2; shift 2;;
--) shift; break;;
-*) echo "$0: Unrecognised option '$1'" >&2
usage >&2; exit 2;;
*) break;;
esac
done
Nastavení (automatického) nahrávání v ~/.bashrc
[ $SHLVL -eq 1 ] && {
file=/tmp/typecript.$$@$(date +%s)
script --timing="$file.time" "$file"
exit
}
Přehrání v terminálu (ideálně ve stejném)
scriptreplay \
-t /tmp/typescript.PID@TIMESTAMP.time \
/tmp/typescript.PID@TIMESTAMP
#!/bin/sed -f
s@Kvůli této otázce stojí za to přijít.@1@g
s@Zajímavé téma.@2@g
s@Nevím/neutrální odpověď.@3@g
s@Nezajímavé téma.@4@g
s@Toto téma by mě odradilo od účasti.@5@g
sum(odpovědí)/count(odpovědí)
csvtool -u TAB col 3-32 "$1" \
| ./t2i \
| awk -F'\t' '
NR==1 { for (i=1;i<=NF;i++) t[i]=$i }
NR>1 { for (i=1;i<=NF;i++)
if ($i) {v[i]+=$i;c[i]++} }
END { for (i=1;i<=30;i++)
if (c[i]) print v[i]/c[i], t[i] }
' \
| sort -n
csvtool col 33 "$1" \
| csvtool -u ^ transpose - \
| sed -r '
s/\^+/^/g
s/\^/\n\n==========\n\n/g
'