From b29b8512813ef2242562f46c08195f14e02f2fd9 Mon Sep 17 00:00:00 2001 From: Ole Tange Date: Sun, 16 Aug 2020 22:18:09 +0200 Subject: [PATCH] binsearch: Supports -q and -2. --- binsearch/binsearch | 98 ++++++++++++++++++++++++++++++++++--------- splitvideo/splitvideo | 2 +- 2 files changed, 79 insertions(+), 21 deletions(-) diff --git a/binsearch/binsearch b/binsearch/binsearch index a0d7017..31dbf6b 100755 --- a/binsearch/binsearch +++ b/binsearch/binsearch @@ -19,16 +19,57 @@ B runs I with a single number. It returns highest value that I succeeds for. +=head1 OPTIONS + +=over 4 + +=item B<-2> + +Instead of the command a single argument, give the command 2 argument: +I I. + +=item B<-q> + +Quiet. Ignore output from B. + + +=back + + =head1 EXAMPLES +=head2 Find the last file + +This is a silly way to find the last non-existing file (namely 244): + + touch {245..800} + binsearch ls + +This is a silly way to find the last file (namely 800): + + touch {1..800} + binsearch ls + =head2 Test a bash function +Test how long an argument /bin/echo can take + . $(which binsearch) singleecho() { /bin/echo $(perl -e 'print "x"x'$1) >/dev/null } binsearch singleecho +=head2 Test a bash function that takes from and to as arguments + +Use a function that takes two arguments + + . $(which binsearch) + greplines() { + env | perl -ne "$1..$2 and print" | grep HOME= + } + binsearch -2 -q greplines + =head1 AUTHOR @@ -60,19 +101,6 @@ B(1) =cut - -# Example: find the max line length -# -# singleecho() { -# /bin/echo $(perl -e 'print "x"x'$1) >/dev/null -# } -# -# multiecho() { -# /bin/echo $(perl -e 'print "x "x'$(($1/2)) ) >/dev/null -# } -# -# binsearch singleecho - binsearch() { _binsearch() { low=$1 @@ -84,7 +112,7 @@ binsearch() { shift shift middle=$(( ( $low + $high ) / 2 )) - if eval "$@ $middle" ; then + if _run $low $middle "$@" ; then low=$middle else high=$middle @@ -92,9 +120,35 @@ binsearch() { _binsearch $low $high "$@" } - low=1 + _run() { + local a="$1" + local b="$2" + shift + shift + # echo "a=$a b=$b $@" + if $opt2 ; then + eval "$not" "$@ $a $b" "$quiet" + else + eval "$not" "$@ $b" "$quiet" + fi + } + + quiet="" + opt2=false + args=$(getopt 'q2' $*) || exit + # now we have the sanitized args... replace the original with it + set -- $args + + while true; do + case $1 in + (-2) opt2=true; shift;; + (-q) quiet=">/dev/null 2>/dev/null"; shift;; + (--) shift; break;; + esac + done + # If function(1) = false: run 'not function()' instead - if eval "$@ $low" ; then + if _run 1 1 "$@" ; then not='' else not='!' @@ -102,17 +156,21 @@ binsearch() { # exponential search for the first value that is false # low = previous value (function($low) == true) # high = low * 2 (function($high) == false) - high=$low - while eval "$not" "$@ $high" 2>/dev/null ; do + high=1 + while _run 1 $high "$@" ; do low=$high high=$(( $high*2 )) + if [ $high -gt 4611686018427387900 ] ; then + echo "$0: Error: exit value does not change of '$@'" >&2 + return + fi done # echo "low: $low high: $high not: $not" - _binsearch $low $high "$not $@" 2>/dev/null + _binsearch $low $high "$@" 2>/dev/null echo $low } -if [ -z "$@" ] ; then +if [ -z "$*" ] ; then # source the bash function # . $(which binsearch) true diff --git a/splitvideo/splitvideo b/splitvideo/splitvideo index d9d5233..9ddda49 100755 --- a/splitvideo/splitvideo +++ b/splitvideo/splitvideo @@ -9,7 +9,7 @@ splitvideo - Split video at time stamp =head1 SYNOPSIS -B time videofile +B I