From 22386b0460c911460a86af2ca2a40c0e54292faa Mon Sep 17 00:00:00 2001 From: flokoe Date: Wed, 5 Jul 2023 11:33:45 +0200 Subject: [PATCH] Convert snipplets to Markdown --- docs/snipplets/add_color_to_your_scripts.md | 103 +++++++++++++ docs/snipplets/awkcsv.md | 45 ++++++ docs/snipplets/filesize.md | 15 ++ docs/snipplets/kill_bg_job_without_message.md | 71 +++++++++ docs/snipplets/largestfile.md | 64 +++++++++ docs/snipplets/pause_command.md | 15 ++ docs/snipplets/prargs.md | 52 +++++++ docs/snipplets/print_horizontal_line.md | 135 ++++++++++++++++++ docs/snipplets/rndstr.md | 123 ++++++++++++++++ docs/snipplets/screen_saverestore.md | 24 ++++ docs/snipplets/ssh_fetchkeys.md | 24 ++++ docs/snipplets/ssh_local_var.md | 17 +++ docs/snipplets/wrapperargs.md | 93 ++++++++++++ docs/snipplets/xclip.md | 34 +++++ 14 files changed, 815 insertions(+) create mode 100644 docs/snipplets/add_color_to_your_scripts.md create mode 100644 docs/snipplets/awkcsv.md create mode 100644 docs/snipplets/filesize.md create mode 100644 docs/snipplets/kill_bg_job_without_message.md create mode 100644 docs/snipplets/largestfile.md create mode 100644 docs/snipplets/pause_command.md create mode 100644 docs/snipplets/prargs.md create mode 100644 docs/snipplets/print_horizontal_line.md create mode 100644 docs/snipplets/rndstr.md create mode 100644 docs/snipplets/screen_saverestore.md create mode 100644 docs/snipplets/ssh_fetchkeys.md create mode 100644 docs/snipplets/ssh_local_var.md create mode 100644 docs/snipplets/wrapperargs.md create mode 100644 docs/snipplets/xclip.md diff --git a/docs/snipplets/add_color_to_your_scripts.md b/docs/snipplets/add_color_to_your_scripts.md new file mode 100644 index 0000000..9f4bd28 --- /dev/null +++ b/docs/snipplets/add_color_to_your_scripts.md @@ -0,0 +1,103 @@ +# Add Color to your scripts + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags : terminal, color +LastUpdate_dt : 2013-03-23 Contributors : Frank Lazzarini, Dan Douglas +type : snipplet + +------------------------------------------------------------------------ + +Make your scripts output more readable using bash colors. Simply add +these variables to your script, and you will be able to echo in color. +(I haven\'t added all the colors available, just some basics) + + # Colors + ESC_SEQ="\x1b[" + COL_RESET=$ESC_SEQ"39;49;00m" + COL_RED=$ESC_SEQ"31;01m" + COL_GREEN=$ESC_SEQ"32;01m" + COL_YELLOW=$ESC_SEQ"33;01m" + COL_BLUE=$ESC_SEQ"34;01m" + COL_MAGENTA=$ESC_SEQ"35;01m" + COL_CYAN=$ESC_SEQ"36;01m" + +Now if you want to output some text in color use *echo -e* instead of +just echo. And always remember to use the *\$COL_RESET* variable to +reset the color changes in bash. Like so \.... + + echo -e "$COL_RED This is red $COL_RESET" + echo -e "$COL_BLUE This is blue $COL_RESET" + echo -e "$COL_YELLOW This is yellow $COL_RESET" + +But also see the notes in [the article about using +terminalcodes](/scripting/terminalcodes) about generating codes and +hardwiring codes. + +This snipplet sets up associative arrays for basic color codes using +`tput` for Bash, ksh93 or zsh. You can pass it variable names to +correspond with a collection of codes. There\'s a `main` function with +example usage. + +``` bash +#!/usr/bin/env bash + +${ZSH_VERSION+false} || emulate ksh +${BASH_VERSION+shopt -s lastpipe extglob} + +# colorSet [ --setaf | --setab | --misc ] var +# Assigns the selected set of escape mappings to the given associative array names. +function colorSet { + typeset -a clrs msc + typeset x + clrs=(black red green orange blue magenta cyan grey darkgrey ltred ltgreen yellow ltblue ltmagenta ltcyan white) + msc=(sgr0 bold dim smul blink rev invis) + + while ! ${2:+false}; do + ${KSH_VERSION:+eval typeset -n "$2"=\$2} + case ${1#--} in + setaf|setab) + for x in "${!clrs[@]}"; do + eval "$2"'[${clrs[x]}]=$(tput "${1#--}" "$x")' + done + ;; + misc) + for x in "${msc[@]}"; do + eval "$2"'[$x]=$(tput "$x")' + done + ;; + *) + return 1 + esac + shift 2 + done +} + +# Example code +function main { + typeset -A fgColors bgColors miscEscapes + if colorSet --setaf fgColors --setab bgColors --misc miscEscapes; then + if ! ${1:+${fgColors[$1]:+false}}; then + printf '%s%s%s\n' "${fgColors[$1]}" "this text is ${1}" "${miscEscapes[sgr0]}" >&3 + else + printf '%s, %s\n' "${1:-Empty}" 'no such color.' + typeset x y + for x in fgColors bgColors miscEscapes; do + typeset -a keys + eval 'keys=("${!'"$x"'[@]}")' + printf '%s=( ' "$x" + for y in "${keys[@]}"; do + eval 'printf "[%q]=%q " "$y" "${'"$x"'[$y]}"' + done + printf ')\n' + done + return 1 + fi + else + echo 'Failed setting color arrays.' + return 1 + fi 3>&1 >&2 +} + +main "$@" + +# vim: set fenc=utf-8 ff=unix ft=sh : +``` diff --git a/docs/snipplets/awkcsv.md b/docs/snipplets/awkcsv.md new file mode 100644 index 0000000..7e9fa76 --- /dev/null +++ b/docs/snipplets/awkcsv.md @@ -0,0 +1,45 @@ +# Using `awk` to deal with CSV that uses quoted/unquoted delimiters + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags : awk, csv +LastUpdate_dt : 2010-07-31 Contributors : SiegX (IRC) type : snipplet + +------------------------------------------------------------------------ + +CSV files are a mess, yes. + +Assume you have CSV files that use the comma as delimiter and quoted +data fields that can contain the delimiter. + + "first", "second", "last" + "fir,st", "second", "last" + "firtst one", "sec,ond field", "final,ly" + +Simply using the comma as separator for `awk` won\'t work here, of +course. + +Solution: Use the field separator `", "|^"|"$` for `awk`. + +This is an OR-ed list of 3 possible separators: + + -------- ----------------------------------------------- + `", "` matches the area between the datafields + `^"` matches the area left of the first datafield + `"$` matches the area right of the last data field + -------- ----------------------------------------------- + +You can tune these delimiters if you have other needs (for example if +you don\'t have a space after the commas). + +Test: + +The `awk` command used for the CSV above just prints the fileds +separated by `###` to see what\'s going on: + + $ awk -v FS='", "|^"|"$' '{print $2"###"$3"###"$4}' data.csv + first###second###last + fir,st###second###last + firtst one###sec,ond field###final,ly + +**ATTENTION** If the CSV data changes its format every now and then (for +example it only quotes the data fields if needed, not always), then this +way will not work. diff --git a/docs/snipplets/filesize.md b/docs/snipplets/filesize.md new file mode 100644 index 0000000..b68af00 --- /dev/null +++ b/docs/snipplets/filesize.md @@ -0,0 +1,15 @@ +# Show size of a file + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags: files, file size +LastUpdate_dt: 2010-07-31 Contributors: Frank Lazzarini type: snipplet + +------------------------------------------------------------------------ + +This is a simple snippet to echo the size of a file in bytes. + + #!/bin/bash + FILENAME=/home/heiko/dummy/packages.txt + FILESIZE=$(wc -c < "$FILENAME") + # non standard way (GNU stat): FILESIZE=$(stat -c%s "$FILENAME") + + echo "Size of $FILENAME = $FILESIZE bytes." diff --git a/docs/snipplets/kill_bg_job_without_message.md b/docs/snipplets/kill_bg_job_without_message.md new file mode 100644 index 0000000..29e9a79 --- /dev/null +++ b/docs/snipplets/kill_bg_job_without_message.md @@ -0,0 +1,71 @@ +# Kill a background job without a message + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags: kill, process +management, jobs LastUpdate_dt: 2010-07-31 Contributors: Jan Schampera +type: snipplet + +------------------------------------------------------------------------ + +When you start background jobs from within a script (non-interactive +shell) and kill it afterwards, you will get a message from the shell +that the process was terminated. + +Example: + + #!/bin/bash + + # example background process + sleep 300 & + + # get the PID + BG_PID=$! + + # kill it, hard and mercyless + kill -9 $BG_PID + + echo "Yes, we killed it" + +You will get something like this: + + $ ./bg_kill1.sh + ./bg_kill1.sh: line 11: 3413 Killed sleep 300 + Yes, we killed it + +This is more or less a normal message. And it can\'t be easily +redirected since it\'s the shell itself that yells this message, not the +command `kill` or something else. You would have to redirect the whole +script\'s output. + +It\'s also useless to temporarily redirect `stderr` when you call the +`kill` command, since the successful termination of the job, the +termination of the `kill` command and the message from the shell may not +happen at the same time. And a blind `sleep` after the `kill` would be +just a workaround. + +The solution is relatively easy: The shell spits that message because it +controls the background job, and when it terminates, the shell will tell +you whenever possible. Now you just need to tell your shell that it is +no longer responsible for that background process. This is done by the +`disown` command, which can take an internal shell job number (like +`%1`) or a process ID as argument. + + #!/bin/bash + + # example background process + sleep 300 & + + # get the PID + BG_PID=$! + + ### HERE, YOU TELL THE SHELL TO NOT CARE ANY MORE ### + disown $BG_PID + ### + + + # kill it, hard and mercyless, now without a trace + kill -9 $BG_PID + + echo "Yes, we killed it" + +That way, you can run and kill background processes without disturbing +messages. diff --git a/docs/snipplets/largestfile.md b/docs/snipplets/largestfile.md new file mode 100644 index 0000000..86eab6b --- /dev/null +++ b/docs/snipplets/largestfile.md @@ -0,0 +1,64 @@ +# Get largest file + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags: directory, recursive, +find, crawl LastUpdate_dt: 2013-03-23 Contributors: Dan Douglas type: +snipplet + +------------------------------------------------------------------------ + +One basic pattern for recursive directory traversal with operations on +files at each node. This gets the largest file in each subdirectory. +Toggling some small details will make it return the smallest, or +traverse breadth-first instead of depth-first. + +``` bash +#!/usr/bin/env bash +# GNU find + bash4 / ksh93v / zsh +# Get the largest file matching pattern in the given directories recursively +${ZSH_VERSION+false} || emulate ksh +${BASH_VERSION+shopt -s lastpipe extglob} + +function getLargest { + typeset -A cur top || return + typeset dir x + for dir in "$2"/*/; do + [[ -d $dir ]] || return 0 + getLargest "$1" "${dir%/}" || return + top[size]=-1 + find "$dir" -maxdepth 1 -type f -name "$1" -printf '%s\0%f\0' | { + while :; do + for x in cur\[{size,name}\]; do + IFS= read -rd '' "$x" || break 2 + done + if (( cur[size] > top[size] )); then + top[size]=${cur[size]} top[name]=${cur[name]} + fi + done + printf '%q\n' "${dir}${top[name]}" + } + done +} + +# main pattern dir [ dir ... ] +function main { + if [[ -n $1 ]]; then + typeset dir pattern=$1 + shift + for dir; do + [[ -d $dir ]] || return + getLargest "$pattern" "$dir" + done + else + return 1 + fi +} + +main "$@" + +# vim: set fenc=utf-8 ff=unix ft=sh : +``` + +## More examples + +- +- diff --git a/docs/snipplets/pause_command.md b/docs/snipplets/pause_command.md new file mode 100644 index 0000000..fd24122 --- /dev/null +++ b/docs/snipplets/pause_command.md @@ -0,0 +1,15 @@ +# Pausing a script (like MSDOS pause command) + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags: terminal, pause, input +LastUpdate_dt: 2010-07-31 Contributors: Jan Schampera type: snipplet + +------------------------------------------------------------------------ + +From the [example section of the read +command](/commands/builtin/read#examples), something that acts similar +to the MSDOS `pause` command: + + pause() { + local dummy + read -s -r -p "Press any key to continue..." -n 1 dummy + } diff --git a/docs/snipplets/prargs.md b/docs/snipplets/prargs.md new file mode 100644 index 0000000..ecaf782 --- /dev/null +++ b/docs/snipplets/prargs.md @@ -0,0 +1,52 @@ +# Print argument list for testing + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags: debug, arguments +LastUpdate_dt: 2013-03-23 Contributors: Snappy (IRC), Dan Douglas type: +snipplet + +------------------------------------------------------------------------ + +Sometimes you might find it useful to see how arguments passed to a +program arrive there. + +Check this script (save it as script file or make a function): + + printf '"%b"\n' "$0" "$@" | nl -v0 -s": " + +It uses the [printf command](/commands/builtin/printf) to generate a +list of arguments, even with escape sequences interpreted. This list is +shown formatted by the nl(1) utility. + +Another alternative with colorized output. If run in Bash, it +temporarily disables all debug output for itself, including the test +that determines whether to hide debug output. In ksh, tracing would have +to be enabled on the function to show debug output, so it works out to +being equivalent. + +``` bash +# Bash or ksh93 debugging function for colored display of argv. +# Optionally set OFD to the desired output file descriptor. +function args { + { BASH_XTRACEFD=3 command eval ${BASH_VERSION+"$(/dev/null + case $- in *x*) + set +x + trap 'trap RETURN; set -x' RETURN + esac +EOF + + [[ ${OFD-1} == +([0-9]) ]] || return + + if [[ -t ${OFD:-2} ]]; then + typeset -A clr=([green]=$(tput setaf 2) [sgr0]=$(tput sgr0)) + else + typeset clr + fi + + if ! ${1+false}; then + printf -- "${clr[green]}<${clr[sgr0]}%s${clr[green]}>${clr[sgr0]} " "$@" + echo + else + echo 'no args.' + fi >&"${OFD:-2}" +} +``` diff --git a/docs/snipplets/print_horizontal_line.md b/docs/snipplets/print_horizontal_line.md new file mode 100644 index 0000000..fd391d5 --- /dev/null +++ b/docs/snipplets/print_horizontal_line.md @@ -0,0 +1,135 @@ +# Print a horizontal line + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags: terminal, line +LastUpdate_dt: 2010-07-31 Contributors: Jan Schampera, prince_jammys, +ccsalvesen, others type: snipplet + +------------------------------------------------------------------------ + +The purpose of this small code collection is to show some code that +draws a horizontal line using as less external tools as possible (it\'s +not a big deal to do it with AWK or Perl, but with pure or nearly-pure +Bash it gets more interesting). + +In general, you should be able to use this code to repeat any character +or character sequence. + +## The simple way: Just print it + +Not a miracle, just to be complete here. + +``` bash +printf '%s\n' -------------------- +``` + +## The iterative way + +This one simply loops 20 times, always draws a dash, finally a newline + +``` bash +for ((x = 0; x < 20; x++)); do + printf %s - +done +echo +``` + +## The simple printf way + +This one uses the `printf` command to print an **empty** field with a +**minimum field width** of 20 characters. The text is padded with +spaces, since there is no text, you get 20 spaces. The spaces are then +converted to `-` by the `tr` command. + +``` bash +printf '%20s\n' | tr ' ' - +``` + +whitout an external command, using the (non-POSIX) substitution +expansion and `-v` option: + +``` bash +printf -v res %20s +printf '%s\n' "${res// /-}" +``` + +## A line across the entire width of the terminal + +This is a variant of the above that uses `tput cols` to find the width +of the terminal and set that number as the minimum field witdh. + +``` bash +printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - +``` + +## The more advanced printf way + +This one is a bit tricky. The format for the `printf` command is `%.0s`, +which specified a field with the **maximum** length of **zero**. After +this field, `printf` is told to print a dash. You might remember that +it\'s the nature of `printf` to repeat, if the number of conversion +specifications is less than the number of given arguments. With brace +expansion `{1..20}`, 20 arguments are given (you could easily write +`1 2 3 4 ... 20`, of course!). Following happens: The **zero-length +field** plus the dash is repeated 20 times. A zero length field is, +naturally, invisible. What you see is the dash, repeated 20 times. + +``` bash +# Note: you might see that as ''%.s'', which is a (less documented) shorthand for ''%.0s'' +printf '%.0s-' {1..20}; echo +``` + +If the 20 is variable, you can use [eval](/commands/builtin/eval) to +insert the expansion (take care that using `eval` is potentially +dangerous if you evaluate external data): + +``` bash +eval printf %.0s- '{1..'"${COLUMNS:-$(tput cols)}"\}; echo +``` + +Or restrict the length to 1 and prefix the arguments with the desired +character. + +``` bash +eval printf %.1s '-{1..'"${COLUMNS:-$(tput cols)}"\}; echo +``` + +You can also do it the crazy ormaaj way™ following basically the same +principle as this [string reverse +example](/commands/builtin/eval#expansion_side-effects). It completely +depends on Bash due to its brace expansion evaluation order and array +parameter parsing details. As above, the eval only inserts the COLUMNS +expansion into the expression and isn\'t involved in the rest, other +than to put the `_` value into the environment of the `_[0]` expansion. +This works well since we\'re not creating one set of arguments and then +editing or deleting them to create another as in the previous examples. + +``` bash +_=- command eval printf %s '"${_[0]"{0..'"${COLUMNS:-$(tput cols)}"'}"}"'; echo +``` + +## The parameter expansion way + +Preparing enough dashes in advance, we can then use a non-POSIX +subscript expansion: + +``` bash +hr=---------------------------------------------------------------\ +---------------------------------------------------------------- +printf '%s\n' "${hr:0:${COLUMNS:-$(tput cols)}}" +``` + +A more flexible approach, and also using modal terminal line-drawing +characters instead of hyphens: + +``` bash +hr() { + local start=$'\e(0' end=$'\e(B' line='qqqqqqqqqqqqqqqq' + local cols=${COLUMNS:-$(tput cols)} + while ((${#line} < cols)); do line+="$line"; done + printf '%s%s%s\n' "$start" "${line:0:cols}" "$end" +} +``` + +## Related articles + +- [printf](/commands/builtin/printf) diff --git a/docs/snipplets/rndstr.md b/docs/snipplets/rndstr.md new file mode 100644 index 0000000..044a3ca --- /dev/null +++ b/docs/snipplets/rndstr.md @@ -0,0 +1,123 @@ +# Print a random string or select random elements + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags: terminal, line +LastUpdate_dt: 2013-04-30 Contributors: Dan Douglas (ormaaj) type: +snipplet + +------------------------------------------------------------------------ + +First off, here is a fast / reliable random string function for scripts +or libraries which can optionally assign directly to a variable. + +``` bash +# Print or assign a random alphanumeric string of a given length. +# rndstr len [ var ] +function rndstr { + if [[ $FUNCNAME == "${FUNCNAME[1]}" ]]; then + unset -v a + printf "$@" + elif [[ $1 != +([[:digit:]]) ]]; then + return 1 + elif (( $1 )); then + typeset -a a=({a..z} {A..Z} {0..9}) + eval '${2:+"$FUNCNAME" -v} "${2:-printf}" -- %s "${a[RANDOM%'"${#a[@]}"']"{1..'"$1"'}"}"' + fi +} +``` + +This example prints 10 random positional parameters and operates on +basically the same principle as the `rndstr` function above. + + ~ $ ( set -- foo bar baz bork; printf '%s ' "${!_[_=RANDOM%$#+1,0]"{0..10}"}"; echo ) + bork bar baz baz foo baz baz baz baz baz bork + +\
This has some interesting option parsing concepts, but is +overly complex. This is a good example of working too hard to avoid an +eval for no benefit and some performance penalty. :/ + +``` bash +# Print or assign a random alphanumeric string of a given length. +# rndstr [ -v var ] len +# Bash-only +rndstr() + if [[ $FUNCNAME == "${FUNCNAME[1]}" ]]; then + # On recursion, this branch unsets the outer scope's locals and assigns the result. + unset -v a b + printf -v "$1" %s "${@:2}" + elif ! { [[ $1 == -v ]] && shift; }; [[ $?+1 -ne $# || ${!#} != +([[:digit:]]) || ( $? -gt 0 && -z $1 ) ]]; then + # This branch does input validation, strips -v, and guarantees we're left with either 1 or 2 args. + return 1 + elif (( ! ${!#} )); then + # If a zero-length string is requested, return success. + return + else + # This line generates the string and assigns it to "b". + local -a a=({a..z} {A..Z} {0..9}) 'b=("${a[RANDOM%'"${#a[@]}"']"{1..'"${!#}"'}"}")' + if (( $# == 2 )); then + # If -v, then pass a variable name and value to assign and recurse once. + "$FUNCNAME" "$1" "${b[@]}" + else + # If no -v, write to stdout. + printf %s "${b[@]}" + fi + fi +``` + +\ + +The remaining examples don\'t use quite the same tricks, which will +hopefully be explained elsewhere eventually. See +[unset](commands/builtin/unset#scope) for why doing assignments in this +way works well. + +This next example is a variation on +[print_horizontal_line](/snipplets/print_horizontal_line). We\'re using +the printf field width specifier to truncate the values of a +`sequence expansion` to one character. + +``` bash +a=({a..z} {A..Z} {0..9}) +printf '%.1s' "${a[RANDOM%${#a[@]}]}"{0..9} $'\n' +``` + +The extra detail that makes this work is to notice that in Bash, [brace +expansion](syntax/expansion/brace) is usually the very first type of +expansion to be processed, always before parameter expansion. Bash is +unique in this respect \-- all other shells with a brace expansion +feature perform it almost last, just before pathname expansion. First +the sequence expansion generates ten parameters, then the parameters are +expanded left-to-right causing the [arithmetic](/syntax/arith_expr) for +each to be evaluated individually, resulting in independent selection of +random element of `a`. To get ten of the same element, put the array +selection inside the format string where it will only be evaluated once, +just like the dashed-line trick: + +``` bash +printf "%.s${a[RANDOM%${#a[@]}]}" {0..9} +``` + +Selecting random elements whose lengths are not fixed is harder. + +``` bash +a=(one two three four five six seven eight nine ten) +printf '%.*s ' $(printf '%s ' "${#a[x=RANDOM%${#a[@]}]} ${a[x]}"{1..10}) +``` + +This generates each parameter and it\'s length in pairs. The \'\*\' +modifier instructs printf to use the value preceding each parameter as +the field width. Note the space between the parameters. This example +unfortunately relies upon the unquoted command substitution to perform +unsafe wordsplitting so that the outer printf gets each argument. Values +in the array can\'t contain characters in IFS, or anything that might be +interpreted as a pattern without using `set -f`. + +Lastly, empty brace expansions can be used which don\'t generate any +output that would need to be filtered. The disadvantage of course is +that you must construct the brace expansion syntax to add up to the +number of arguments to be generated, where the most optimal solution is +its set of prime factors. + +``` bash +a=(one two three) +echo "${a[RANDOM%${#a[@]}]}"{,}{,,,,} +``` diff --git a/docs/snipplets/screen_saverestore.md b/docs/snipplets/screen_saverestore.md new file mode 100644 index 0000000..a1ca56a --- /dev/null +++ b/docs/snipplets/screen_saverestore.md @@ -0,0 +1,24 @@ +# Save and restore terminal/screen content + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags: terminal, restore +screen LastUpdate_dt: 2010-07-31 Contributors: Greg Wooledge type: +snipplet + +------------------------------------------------------------------------ + +This cool hack uses the terminal capabilities (see `terminfo(5)` manual) +**smcup** and **rmcup** to save and restore the terminal content. + +For sure, you've already seen those programs that restore the terminal +contents after they did their work (like `vim`). + + # save, clear screen + tput smcup + clear + + # example "application" follows... + read -n1 -p "Press any key to continue..." + # example "application" ends here + + # restore + tput rmcup diff --git a/docs/snipplets/ssh_fetchkeys.md b/docs/snipplets/ssh_fetchkeys.md new file mode 100644 index 0000000..b9c1e49 --- /dev/null +++ b/docs/snipplets/ssh_fetchkeys.md @@ -0,0 +1,24 @@ +# Fetching SSH hostkeys without interaction + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags: ssh, ssh-keys +LastUpdate_dt: 2010-07-31 Contributors: Jan Schampera + +------------------------------------------------------------------------ + +Applies at least to `openssh`. + +To get the hostkeys for a server, and write them to `known_hosts`-file +(to avoid that yes/no query when the key isn\'t known), you can do: + + ssh-keyscan -t rsa foo foo.example.com 1.2.3.4 >> ~/.ssh/known_host + +This example queries the hostkeys for the very same machine, but under 3 +different \"names\" (hostname, FQDN, IP) and redirects the output to the +`known_hosts`-file. + +[**Notes:**]{.underline} + +- if done blindly, the `known_host`-file may grow very large. It might + be wise to check for key existance first +- if multiple keys for the same host exist in `known_hosts`, the first + one is taken (which might be an old or wrong one) diff --git a/docs/snipplets/ssh_local_var.md b/docs/snipplets/ssh_local_var.md new file mode 100644 index 0000000..093c07b --- /dev/null +++ b/docs/snipplets/ssh_local_var.md @@ -0,0 +1,17 @@ +# Run some bash commands with SSH remotely using local variables + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags: ssh, variables +LastUpdate_dt: 2010-07-31 Contributors: cweiss type: snipplet + +------------------------------------------------------------------------ + +In this example, we want to make sure a certain file exists on the +remote server: + + file=/tmp/file.log + ssh ${options} ${login} "if [ ! -e '$file' ] ; then touch '$file' ; fi" + +Notice the command is surrounded by double quotes, and the \$file +variable is surrounded by single quotes. That has the effect to be +wordsplit-proof in the local shell (due to the double-quotes) and in the +remote shell (due to the single-quotes). diff --git a/docs/snipplets/wrapperargs.md b/docs/snipplets/wrapperargs.md new file mode 100644 index 0000000..59341b4 --- /dev/null +++ b/docs/snipplets/wrapperargs.md @@ -0,0 +1,93 @@ +# Generate code with own arguments properly quoted + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags: arguments, quoting, +escaping, wrapper LastUpdate_dt: 2010-07-31 Contributors: Jan Schampera +type: snipplet + +------------------------------------------------------------------------ + + Keywords: arguments,escape,quote,wrapper,generate + -------------- ----------------------------------------- + Contributor: self + +There are situations where Bash code needs to generate Bash code. A +script that writes out another script the user or cron may start, for +example. + +The general issue is easy, just write out text to the file. + +A specific detail of it is tricky: If the generated script needs to call +a command using the arguments the first original script got, you have +problem in writing out the correct code. + +I.e. if you run your generator script like + + ./myscript "give me 'some' water" + +then this script should generate code that looks like + + echo give me 'some' water" + +you need correct escapes or quotes to not generate shell special +characters out of normal text (like embedded dollar signs `$`). + +**[Solution:]{.underline}** + +A loop over the own arguments that writes out properly quoted/escaped +code to the generated script file + +There are two (maybe more) easy options: + +- writing out singlequoted strings and handle the embedded + singlequotes +- the [printf command](/commands/builtin/printf) knows the `%q` format + specification, which will print a string (like `%s` does), but with + all shell special characters escaped + +## Using singlequoted string + + #!/bin/bash + + # first option: + # generate singlequoted strings out of your own arguments and handle embedded singlequotes + # here to call 'echo' in the generated script + + { + printf "#!/bin/bash\n\n" + printf "echo " + for arg; do + arg=${arg/\'/\'\\\'\'} + printf "'%s' " "${arg}" + done + + printf "\n" + } >s2 + +The generated script will look like: + + #!/bin/bash + + echo 'fir$t' 'seco "ond"' 'thir'\''d' + +## Using printf + +The second method is easier, though more or less Bash-only (due to the +`%q` in printf): + + #!/bin/bash + + { + printf "#!/bin/bash\n\n" + printf "echo " + for arg; do + printf '%q ' "$arg" + done + + printf "\n" + } >s2 + +The generated script will look like: + + #!/bin/bash + + echo fir\$t seco\ \"ond\" thir\'d diff --git a/docs/snipplets/xclip.md b/docs/snipplets/xclip.md new file mode 100644 index 0000000..e26572e --- /dev/null +++ b/docs/snipplets/xclip.md @@ -0,0 +1,34 @@ +# X-Clipboard on Commandline + +\-\-\-- dataentry snipplet \-\-\-- snipplet_tags: clipboard, x11, xclip, +readline LastUpdate_dt: 2010-07-31 Contributors: Josh Triplett type: +snipplet + +------------------------------------------------------------------------ + + # Make Control-v paste, if in X and if xclip available - Josh Triplett + if [ -n "$DISPLAY" ] && [ -x /usr/bin/xclip ] ; then + # Work around a bash bug: \C-@ does not work in a key binding + bind '"\C-x\C-m": set-mark' + # The '#' characters ensure that kill commands have text to work on; if + # not, this binding would malfunction at the start or end of a line. + bind 'Control-v: "#\C-b\C-k#\C-x\C-?\"$(xclip -o -selection c)\"\e\C-e\C-x\C-m\C-a\C-y\C-?\C-e\C-y\ey\C-x\C-x\C-d"' + fi + +The behaviour is a bit tricky to explain: + +- kill text after the cursor + - since the kill command **wants** text, it blindly adds a fake + text \"#\" here +- kill text before the cursor + - since the kill command **wants** text, it blindly adds a fake + text \"#\" here, too +- write out `"$(xclip -o -selection c)"` +- run Control-Meta-e (shell-expand-line) to expand the + `"$(xclip -o -selection c)"` +- yank the previously killed text back where it belongs + +Of course you can use any other command, you\'re not limited to `xclip` +here. + +Note: C-@ as well as M-SPC both works and set the mark for me \-- pgas