Useful scripts

aragats

Daemon

Reaction score: 473
Messages: 1,136

(about parts of the command line disappearing)
....
I'm not sure from mind what causes this, come to think of it I suppose it could also be an effect of setting up a specific prompt...
I don't see such thing with ksh93 in urxvt.
ShelLuser , since you use Xorg, have you tried running resize when such things happen?
I noticed that sometimes terminals get screwed up by "bad outputs" of certain commands.
 

ShelLuser

Son of Beastie

Reaction score: 1,696
Messages: 3,512

Thanks for your comments, both of you :)

Out of curiosity, why is ksh your favorite? And which one of the various implementations?
I use shells/pdksh on all my servers, and the 'why' part has everything to do with SunOS / Solaris. There is no rational reasoning other than ksh being the standard on Sun Solaris and that was the very first Unix environment I learned to operate (and I loved every part of it).

Around the 90's during my internship within Olivetti computers did I learn about this 'magical' operating system called Unix which could outperform Windows on every possible geek level. Transporting files between PC's? No need for floppies nor a special parallel cable with laplink or Norton Commander. Instead even a serial cable would do and you'd be able to simply communicate between those machines with nothing other than the Unix OS itself. Even Windows 3.11 couldn't pull that off!

Learned about Linux (RedHat 'Picasso') and dove in head first.

So when I became a sysadmin at my first job and suddenly discovered that a sub-group within our company used a Sun Sparcstation running Sun Solaris ("Unix") plus Smartstream (database server) while they were having issues I knew exactly what to do. Well, I didn't but I knew man man, learned about catman and then apropos then and there. Fixed the network hiatus by switching the server from DHCP client (provided by a flakey Novell server) to a static IP and everyone was happy. So happy that I was sent onto 2 Sun Solaris training camps, paid for by said company. That was the beginning of the end ;)

I didn't switch from Linux to FreeBSD, I switched from Solaris 10/x86 to FreeBSD :)

Back then (around 2009 I think?) FreeBSD was the perfect Solaris replacement for me; UFS & ZFS, Jails vs. Zones, ipf (Solaris firewall) and a sane user land.

I exchanged ipfilter for pf last year or so, but I'm still a die hard Korn shell user ;)

Note that I don't use it for scripting or such, only interaction. Mine even runs in vi mode by default, I love it:

Code:
peter@zefiris:/home/peter $ cat .kshrc
if [ "`basename ${0#-}`" == "ksh" ]; then
   set -o posix -o braceexpand -o vi -o vi-tabcomplete;
   PS1="`whoami`@`hostname -s`:\${PWD} \$ ";
fi
Very important detail is that for me it's not only about work, I also actually enjoy working with this stuff.

I really should change my PS1 sometime, these days you can swap out your home for ~ or make it cut longer pathlines into smaller bits but I never took the time to do so and just kept using what I already had & once learned :)

Sorry for a brief ramble there, but yah ;)

ShelLuser , since you use Xorg, have you tried running resize when such things happen?
I noticed that sometimes terminals get screwed up by "bad outputs" of certain commands.
No, never bothered with resize(1) (did look it up as you can tell ;) ). But this has nothing to do with X directly though, this also happens if I'm on a regular console (I never automatically log onto the GUI).

But it's shell related. As olli@ mentioned above; this doesn't happen with sh (which I also tried) but more so with ksh. Still, it doesn't bother me, also because my vi mode allows to be move back and forth onto such a commandline with easy (escape ^; done).
 
Last edited:

olli@

Well-Known Member
Developer

Reaction score: 275
Messages: 315

I am a hobbyist with respect to IT. But this is why I really like shells/ksh93. I have not tried shell/pdksh yet. Learning some key bindings and use them for many tools is marvelous.
But vi-mode is not unique to ksh. All common shells support vi-mode line editing. bash and zsh do, and even FreeBSD's /bin/sh supports it (even though it's otherwise not very well-suited for interactive use).
 

k.jacker

Aspiring Daemon

Reaction score: 344
Messages: 590

If anyone has ever tried to format multimedia/mplayer's "ICY Info" output strings from a script, has maybe grown some grey hair.
There are a lot of examples on the web using grep, cut, awk and sed, and that's what I was using, too.
Still it had some weaknesses.

Today I stumbled over some of my own examples from earlier this year, where I was learning to use back references.

What I use now, has become so short and simple, with no weaknesses anymore, I'd like to share it.
Code:
mplayer -msglevel all=0:demuxer=4 <url to radio stream> | grep --line-buffered -oe "\([\']\)[[:print:]]*\1"
Nice, tmux statusline ready output :D
'Dynoro feat. Gigi D'Agostino - In My Mind'
'Udo Lindenberg - Cello (feat. Clueso)'
'www.antennemv.de'
'Depeche Mode - People Are People'
'Milow - Lay Your Worry Down (feat. Matt Simons)'
'The Avener - Fade Out Lines'
'Jason Mraz - Have It All'
'R.E.M. - Losing My Religion'
'Adele - Someone Like You'


What the backreference does is, it greps everything between the first and the last single quote from the string:
ICY Info: StreamTitle='Dynoro feat. Gigi D'Agostino - In My Mind';

Redirect the output to a file and add the following to ~/.tmux conf
Code:
set -g status-left '#(tail -n1 /tmp/<filename>)'
 

Sensucht94

Well-Known Member

Reaction score: 387
Messages: 388

pdksh, and all its idependent derivatives (mksh, GNU ksh, OpenBSD ksh -oksh-, NetBSD ksh, AmigaOS SKsh) are originally born as free AT&T ksh88 clones, the way Linux is Unix clone (completely written from scratch, different at its core, compatible at its surface); the ksh one can find on commercial Unices, is AT&T ksh93, a new overall reshaped and improved version of ksh88, first released in '94, opensource under Eclipse Public License as of 2005, Illumos default system interpreter, developed until 2014 when the last version was released, and presumably now discontinued.
dtksh (CDE's shell, used also in the dtlogin Xsession script) and tksh are ksh93 derivatives providing shell-level mapping for Motif and Tk widget toolkits respectively. rksh is ksh93 acting in restricted mode

Although many patches providing cross-compatibility with new ksh93 additions were submitted to the various pksh versions throughtout the years, pdksh derivatives and ksh93 are not fully compatible, while pdksh derivatives usually are with one another

Generally speaking ksh93 is more complex (have a look at sources on github), one may say bloated;
Of all the pdksh derivatives, mksh is the most featured, providing bash/zsh -like extentions, while oksh is the most stripped down, clean, fast, but also barebones

None of those shells are POSIX-compliant by default (in spite of their significantly stronger adherence to POSIX compared to bash), but can operate in POSIX mode (set -o posix), which is what they do when invoked as /bin/sh
 

Vull

Well-Known Member

Reaction score: 104
Messages: 258

I used the AIX version of ksh for years in my work environment which was dominated by AIX, SCO Openserver 5, and Red Hat 6.2, and it was my favorite shell. Here's an old script I wrote for changing the PS1 prompt, just to remind myself and other programmers which machine we had telnetted into, and to put the pathname in the prompt, which still wasn't all that common a thing in the 90s, and SCO still had just the "$ " or "# " prompts, and lacked the capability of putting the pwd present working directory pathname in the prompt. It's a bit crude and I'm almost ashamed to admit I wrote it, but it worked then and still works now. I no longer use AIX, SCO, or Red Hat, and have since modified it to work on FreeBSD and MacOS X 10.5.8, but it still has some of the old residue from those original three systems. Originally it was intended to use different sets of braces in the set {},[],<> to indicate the "flavor" of the OS, and it still has some of that in there too...

Edited March 12, 2019 - this is the latest improved version as just tested on freebsd 12.0-RELEASE, Debian 9.6, and Mac OS X 10.5.8 - this version uses id -u to detect if a user has used su -m to gain super-user status in FreeBSD, and accordingly shows "#" instead of "$" at the end of the prompt, even when the USER and HOME environment variables are neither root nor /root (assuming that the user's default SHELL Is /bin/sh).
Code:
#!/bin/sh
# wasatps1 - format PS1 shell prompts for bash, ksh, or sh shells
# 2019-03-12 t jch
#
# --- Usage:  PS1=`wasatps1`;export PS1
#
# --- Show $PWD (print working directory) if shell is capable (bash or ksh).
# --- Show hostname or user name as specified locally by SHOWHOST and SHOWUSER.
# --- Indicate if user is superuser by "$" (user) or "#" (super-user) suffix.
#
SHOWHOST=1 #--- 0=don't show hostname in shell prompt, 1=show it.
SHOWUSER=1 #--- 0=don't show username in shell prompt, 1=show it.
PROMPTLINES=1 #--- 1=1 line prompt, 2=2 line prompt
              #--- NOTE: sh doesn't interpret "\n" and so won't display 2 lines
#
#--- Only interpret bash, ksh, or sh shells. While checking the shell name, also

#--- set CANPWD=1 if shell prompt is capable of displaying the working directory

if [ "`echo $SHELL |grep -c /bash`" != "0" ];then
        THISSH=bash
        CANPWD=1
elif [ "`echo $SHELL |grep -c /ksh`" != "0" ];then
        THISSH=ksh
        CANPWD=1
elif [ "`echo $SHELL |grep -c /sh`" != "0" ];then
        THISSH=sh
        CANPWD=1
else #--- if neither bash, ksh, or sh is the shell, return $PS1 unchanged
        echo "$PS1"
        exit 0
fi
#--- Sniff for AIX, Linux, SCO Openserver, Mac OSX, and FreeBSD systems. Also
#--- set ISSUPER=1 if shell is running as super-user.
ISSUPER=0
if [ -d /usr/lpp/bos ];then
        FLAVOR=aix #--- IBM AIX operating system for RISC system architecture
        PREFIX=\< ; SUFFIX=\>
        if [ "$LOGIN" = "root" ];then ISSUPER=1 ; fi
elif [ "`which freebsd-version`" != "" ];then
        FLAVOR=freebsd
        PREFIX=\( ; SUFFIX=\)
        #if [ "$HOME" = "/root" ]||[ "$USER" = "root" ];then ISSUPER=1; fi
        if [ "`id -u`" = "0" ]; then ISSUPER=1; fi
elif [ "`ls /boot/vmlin* 2>/dev/null`" != "" ];then
        FLAVOR=linux #--- presumably Red Hat Linux 6.2 or newer ---#
        PREFIX=\[ ; SUFFIX=\]
        if [ "$HOME" = "/root" ];then ISSUPER=1 ; fi
elif [ -d /var/opt/K/SCO ];then
        FLAVOR=sco #--- presumably SCO Unix OpenServer 5 or better ---#
        PREFIX=\( ; SUFFIX=\)
        if [ "`env |grep '_=' |grep -c su`" = "1" ];then ISSUPER=1 ; fi
        if [ "$PS1" = "# " ]||[ "$LOGNAME" = "root" ];then ISSUPER=1 ; fi
elif [ -f /mach_kernel ];then
        FLAVOR=mac #--- presumably Apple Mac OS X or higher ---#
        PREFIX=\{ ; SUFFIX=\}
        if [ "$HOME" = "/var/root" ];then ISSUPER=1; fi
else #--- if none of the above systems, return $PS1 unchanged & exit normally
        echo "$PS1"
        exit 0
fi
#--- Get host name if specified, but strip off any domain name suffixes.
if [ "$SHOWHOST" != "0" ];then
        SHOWHOST=`hostname`
        SHOWHOST=`echo $SHOWHOST |awk 'BEGIN { FS = "." } { printf("%s",$1) }'`
fi
#--- format the shell prompt for the host, shell, and super-user level at hand
if [ "$SHOWUSER" != "0" ] || [ "$SHOWHOST" != "0" ];then
        PS1=$PREFIX; else PS1=
fi
if [ "$THISSH" = "bash" ];then
        if [ "$SHOWUSER" != "0" ];then PS1=$PS1"\u" ; fi
        if [ "$SHOWHOST" != "0" ];then PS1=$PS1"@\h" ; fi
else
        if [ "$SHOWUSER" != "0" ];then PS1=$PS1$LOGNAME; fi
        if [ "$SHOWHOST" != "0" ];then PS1=$PS1"@"$SHOWHOST; fi
fi
if [ "$CANPWD" != "0" ];then
        if [ "$SHOWUSER" != "0" ]||[ "$SHOWHOST" != "0" ];then
                PS1=$PS1" "
        fi
        if [ "$THISSH" = "sh" ];then
                PS1=$PS1"\w"
        else
                PS1=$PS1"\${PWD}"
        fi
fi
if [ "$SHOWUSER" != "0" ] || [ "$SHOWHOST" != "0" ];then
        PS1=$PS1$SUFFIX
fi
if [ $PROMPTLINES -eq 2 ];then PS1=$PS1"\n"; fi

if [ "$ISSUPER" != "0" ];then
        PS1=$PS1"# "
else
        PS1=$PS1"$ "
fi
echo "$PS1"
exit 0
 
Last edited:

Vull

Well-Known Member

Reaction score: 104
Messages: 258

Self-extracting installer script:

The "exex" script has 2 functions. If it's executed with command line arguments, it attempts to perform the Create() function, and if it has no command line arguments, it attempts to perform the Extract-and-Execute function. This has been tested on FreeBSD 11.2 and 12.0, and on Debian 9.5 and 9.6.

1. The "Create()" function creates a single executable file by concatenating 3 separate files, one after the other:
1. A. The first file included in the self-extracting executable is the exex script itself.
1. B. The second file included in the self-extracting executable is a separate script which will run right after the archive is extracted. In the example provided here, it will unzip the archive and start the installation of the software in the archive.
1. C. The third file included in the self-extracting executable is the archive itself.

2. The "Extract()" function is the function which extracts the archive from the concatenated file. After the extraction has been done, the 2nd file will be executed automatically. The automatic execution depends on the fact that the exex script has no 'exit' statement, and therefore, since the 2nd file comes right after the first, control will pass immediately from the last executed statement in the first file to the first executable statement in the 2nd file. For further documentation please refer to the comments in the two scripts. The first script is the exex file itself, and the 2nd script is an example of what can be done automatically after the archive has been extracted.

exex
Code:
#!/bin/sh
# 2018-12-19 w jch - modified for better posix compliance
#-------------------------------------------------------------------------------
# exex - create the SXE (mode=c), or (ex)tract & (ex)ecute the SXE (mode=x)
# ----   ------     ---  ------       --          --           ---  ------
# SXE = (S)elf-e(X)tracting-(E)xecutable script file

Create() { #--- Create the whole self-extracting archive and executable script.

  #--- get the file size of this file, which will be the first file in the sxe,

  size1=`ls -l $0 |awk 'BEGIN{FS=" "}{printf("%s",$5)}'`

  #-- and the size of the user-provided script file, which will be the 2nd file,

  size2=`ls -l $script |awk 'BEGIN{FS=" "}{printf("%s",$5)}'`
  
  #--- and the size of the user-provided archive, which will be the 3rd file

  # size3=`ls -l $archive |awk 'BEGIN{FS=" "}{printf("%s",$5)}'`

  #--- NOTE: we don't actually need to know size3, hah, so I commented it out.

  #--- Build a candidate line 2, which will be interpreted as a comment when
  #--- the combined script files run. The two scripts will execute one after the
  #--- other, like a single script. The size info line 2 comes right after the
  #--- shebang line, i.e., the line that says: "#!/bin/sh" ... The magical
  #--- importance of the inserted 2nd line is that it provides info to the
  #--- Extract() function, as to exactly where the user-provided archive file
  #--- begins, so it can be extracted from the sxe, and made into a usable
  #--- copy of the original archive. Thus, it must also contain the name of that
  #--- original user-provided archive. This Create() function will also insert
  #--- an "exit 0" at the end of the user provided script file, so the shell
  #--- won't try to execute the archive, which will be tucked in this file when
  #--- the exex script and the user provided script are executed together, as
  #--- one. The shell will interpret the two scripts together in one pass, like
  #--- they were a single script, and that's what makes it "self-executing."

  exitcommand="exit 0"    #--- The actual length of this line will be 7,
  # exitcommandlength=7   #--- 6 for the characters, plus 1 for the "\n" char.

  #--- Now begins a series of approximations of the exact offset of the archive.

  offset=$(($size1+$size2+7+4+${#archive})); # We know where the 7
  #--- in this offset sum came from, and the 4 in the same calculation is for
  #--- the length of the 3 # chars and the \n in the line 2 info comment. Then
  #--- we add the length of the NAME of the archive file, NOT the length, or
  #--- the size, of the actual archive file, because the name of the file will
  #--- be the 2nd item of info in the info comment line.
  
  #--- Now the 2nd, closer approximation: The problem is the decimal string len.
  offset2=$(($offset+${#offset})) #--- Add string length of offset.
  offslen=${#offset} #--- The approx. length of the decimal string.
  offslen2=${#offset2} #--- offslen is 1 estimate, offslen2, closer

  #- Make offslen2 the EXACT offset, after 1st seeing if the length "rolls over"
  #- (like speedometer mileage), for example, 999 is 3 digits, 1000 is 4 digits.

  if [ $offslen2 -gt $offslen ]; then $offset2=$(($offset2+1)); fi
  line2='#'$offset2'#'$archive"#" #--- Now, finally, offset2 = the exact offset

  # Oh I know, I could've just used a few # chars for padding, but it was fun:)!

  #--- Create a temporary filename for the tmp directory,

  tmpf=$HOME/grip/tmp/exexarchive.`wasat.who` #( wasat.who = pts.0, tty1, etc.,)
                                              #( something unique to this user.)

  #--- add the first line of this file (the shebang line) to the temporary file,

  line1=`awk 'NR==1{print $0}' $0` #(Select NR (Number of Record)=1,which means)
                                   #(the 1st line. (R)ecord=row, (F)ield=column)
  echo $line1 > $tmpf

  #--- followed by the 2nd info or comment line, which we need to insert, so the
  #--- Extract() function can use that info, and will know where to find it,

  echo $line2 >> $tmpf

  #--- Now, add lines 2 through the end of file, of the exex file, after line 2,

  tail -n +2 $0 >> $tmpf

  #--- and then add all the lines of the user supplied script file after that,

  cat $script >> $tmpf

  #--- and add the exit 0 command after the user supplied script, just in case,
  #--- because we wouldn't want the shell interpreter interpreting the archive.

  echo $exitcommand >> $tmpf

  #--- and add the archive file,

  cat $archive >> $tmpf

  #--- and rename it, at the same time moving to the path specified in the name,

  mv $tmpf $sxe
  chmod +x $sxe #--- and then, finally, make the whole file executable.

  echo 'Finished creating "'$sxe'"'
}

Extract() { #--- Extract the user-provided archive file, and then the 2nd part
            #--- of this file will execute, right after this function executes.

  #--- The shell interpreter's timing considerations will make the 2nd script
  #--- wait for the archive to be extracted, just like we have to wait for a
  #--- command to finish before the shell shows us the next command prompt.

  line2=`head -n 2 $0 |awk 'NR==2{print $0}'`
  offset=`echo $line2 |awk 'BEGIN{FS="#"}{printf("%s",$2)}'`
  archive=`echo $line2 |awk 'BEGIN{FS="#"}{printf("%s",$3)}'`
  if [ ! -f $archive ]; then
    tail -c +$(($offset+1)) $0 > $archive
  fi
}

Syntax() { #--- Complain about syntax errors and/or any type of errors, & exit.

  if [ "$mes" != "" ]; then
    echo
    echo "Error:  *** "$mes" ***"
  fi
  echo
  echo "Syntax:"
  echo "  exex scriptFile archiveFile nameForNewSelfExtractingExecutable"
  echo
  exit 1
}

#--- ma(in lo)gic

#--- Determine if we're running in create mode, or in extract and execute mode.

mode= #--- if filename is exex, run in create mode, otherwise, use ex & ex mode

mes= #--- error message for the Syntax() function

name=`echo $0 |awk 'BEGIN{FS="/"}{printf("%s",$NF)}'` #--- this filename

if [ "$name" = "exex" ]; then mode=c; else mode=x; fi

case "$mode" in

  ("c") #--- Create the archive

    #--- First check the command line arguments.
    exex=$0
    script=$1
    archive=$2
    sxe=$3 #--- S.X.E. is bad language for (S)elf e(X)ecuting (E)xecutable.

    if [ "$sxe" = "" ]; then Syntax; #--- If last one is empty all 3 are empty.
    elif [ ! -f $script ]; then
      mes='Script file: "'$script'" not found.'; Syntax
    elif [ ! -f $archive ]; then
      mes='Archive file: "'$archive'" not found.'; Syntax
    elif [ -f $sxe ]; then
      mes='Target file: "'$sxe'" already exists.'; Syntax 
    fi

    Create
     ;;

  ("x") #--- Extract the user-provided archive file, which is file section 3 in
        #--- this weird file, and then let the shell interpreter start
        #--- interpretting the user-provided script, which is file section 2.
        #--- We are now close to the end of file section 1. Thanks for visiting.

    Extract
     ;;
  (*) ;;
esac

#--- PROGRAMMER(S): THIS IS IMPORTANT! Do NOT add an exit command, and PLEASE,

# exit 0 #--- PLEASE, DON"T uncomment THIS line, or the user's script file
#        won't be executed! Which would thwart the whole purpose of this file.

#--- BECAUSE: we want the two scripts to run together, like a single script.
#-------------------------------------------------------------------------------
execute-install
Code:
#!/bin/sh
# execute-install - bootstrap script for self-extracting installer which s.b.
#   created by the non-root user running exex w/ this 2 step command sequence:
#
# cd $HOME
# exex grip/install/freebsd11.2.d/execute-install xfer.tar install-wasat
#
# Note: this is not an executable script, but rather, install-wasat will be.

# 2018-8-30 h 081 jch |# 2018-8-31 f 079 jch # 2018-9-16 n 088 jch
# 2018-10-15 m 094 jch |# 2018-10-20 m 094 jch |# 2018-11-3 s jch
# 2018-11-24 s jch - from grip/install/debian9.5.d -> grip/install/freebsd11.2.d

dv='11.2'
installdir='grip/install/freebsd'$dv'.d'
subnet=dashnet

oldpath=`pwd`
cd $HOME
#--- Check if system is partially installed (and still needs to have setup done)

echo "Checking if system is already (partially) installed ... "

h=/usr/local/www/apache24/data
if [ -f $h/wasat/setup-wasat.php ]; then
  DISPLAY=:0; export DISPLAY

  firefox "https://`hostname`.$subnet/wasat/setup-wasat.php" &

  cd $oldpath
  exit 0
fi
#--- Check if system appears to be completely or partly/unsuccessfully installed

if [ -d $h/wasat ]||[ -d $HOME/grip ]; then
  echo
  if [ -d $h/wasat ]; then
    echo 'Your system appears to be already installed in "'$h'/wasat/".'
  else
    echo "Your system appears to be partially installed."
    echo "There is a 'grip' directory in your home directory."
  fi
  cd $oldpath
  exit 0
fi
#--- Start unpacking the xfer.tar archive

echo -n "... Preparing to install the pre-packaged software ... "

tar -xf xfer.tar
tar -xzf xfer/grip.tar.gz
if [ ! -d $HOME/Desktop ];then mkdir $HOME/Desktop; chmod 700 $HOME/Desktop; fi
if [ ! -d $HOME/Desktop/0 ]; then mkdir $HOME/Desktop/0; fi
if [ "`ls xfer/wasat* 2>/dev/null`" != "" ]; then
  cp -p xfer/wasat* Desktop/0/
fi
echo
#--- Execute the install script

echo "... Starting the installation process ..."

$installdir/install |tee $installdir/install.log

inp=
if [ -f $h/wasat/setup-wasat.php ]; then
  echo
  while [ "$inp" != "y" ]&&[ "$inp" != "n" ];do
    echo -n "Would you like to continue with the setup now? [y/n] "; read inp;
    if [ "$inp" != "" ]; then inp=`echo $inp | tr [:upper:] [:lower:]`; fi
    case "$inp" in ("yes") inp=y;; ("no") inp=n;; ("y");; ("n");;
      (*) echo "Please answer yes or no (or y or n)."; inp="";;
    esac
  done
  if [ "$inp" = "y" ]; then
    echo "Launching the setup program now..."
    DISPLAY=:0; export DISPLAY
    firefox "https://`hostname`.$subnet/wasat/setup-wasat.php" &

    #--- message to keep terminal open in case installer was desktop-launched
    echo
    echo "Please leave this Terminal open until your Firefox session is"
    echo "closed, or your Firefox session may also be suddenly closed."
    echo
  fi
fi
cd $oldpath
exit 0
 

Vull

Well-Known Member

Reaction score: 104
Messages: 258

Shell script to display FreeBSD package dependencies recursively:

Code:
#!/bin/sh
# pkg-dependencies - recursively display package dependencies / FreeBSD 12.0R
# 2019-1-18 f jch

# Uses a /tmp dir. work file to avoid listing the same packages more than once.
# May be interrupted with CTRL-C

trap Cleanup 1 2 3 6

Cleanup() {
  #-- delete the work file(s)
  rm -rf /tmp/pkg-dependencies-work*
  exit 1
}
Recurse() {
  pkgroot=$1
  if [ "$2" = "" ];then
    lvl=0 #-- recursion level
    pid=$$ #-- pid of top level parent process
  else
    lvl=$2
    pid=$3
  fi
  workf=/tmp/pkg-dependencies-work.$pid
  if [ $lvl -eq 0 ]; then
    #-- create work file
    rm -rf $workf
    touch $workf
  elif [ ! -f $workf ]; then
    exit 1 #-- program interrupt must have occurred and deleted the work file
  fi
  #-- generate list of dependent packages using pkg info command
  list=$(pkg info -d $pkgroot)
  n=0
  for pkg in $list; do
    n=$(($n+1)) #-- sequence number in list from pkg info command
    if [ $n -eq 1 ]; then #-- this is package name arg followed by a ":" char
      #-- display the top level package name followed by ":"
      if [ $lvl -eq 0 ]; then echo 'Package dependencies for '$pkg; fi
    else
      #-- for sub-packages, display package name after a "tab line" of "." chars
      tab=
      x=$(($lvl+1)) #-- display one "." for level 0, 2 for level 1, etc.
      while [ $x -gt 0 ]; do
        tab=$tab"."
        x=$(($x-1))
      done
      #-- check work file to learn if package name has already been displayed
      grepout=$(grep $pkg $workf)
      echo $pkg >>$workf #-- add package name to work file
      if [ "$grepout" = "" ]; then #-- package has not been displayed so do it
        echo $tab $pkg #-- display tab line and package name
        $0 $pkg $(($lvl+1)) $pid #-- invoke recursion to show sub-dependencies
      fi
    fi
  done
  if [ $lvl -eq 0 ]; then
    rm -f $workf
  fi
}

Syntax() {
  echo
  if [ "$mes" != "" ]; then
    echo "Error:  *** "$mes" ***"
    echo
  fi
  echo "Syntax: pkg-dependencies packageName"
  echo
  exit 1
}

mes=
if [ "$1" = "" ];then Syntax; fi
Recurse $*
exit 0
 

olli@

Well-Known Member
Developer

Reaction score: 275
Messages: 315

While we're at it ... This is my version of a script that displays package dependencies recursively. It doesn't use any temporary files.
Code:
#!/bin/sh -
#
#   This script calls "pkg info" repeatedly in order to generate
#   recursive lists of dependecies (-d) or required-by (-r).
#

set -Cefu
ME="${0##*/}"

DEBUG=false
#DEBUG=true

if $DEBUG; then
        echo "#### $ME $*" >&2
fi

Usage()
{
        echo "Usage:  $ME {-d | -r} <package> [...]" >&2
        exit 1
}

if [ $# -lt 2 ] || [ "x$1" != x-d -a "x$1" != x-r ]; then
        Usage
fi

FLAG="$1"
shift

ARGS="$*"
LIST="%"

while :; do
        if $DEBUG; then
                echo "==== pkg info -q $FLAG $ARGS" >&2
        fi
        PKGS="$(pkg info -q $FLAG $ARGS)" || {
                echo "WARNING: Exit code from pkg: $?" >&2
        }
        if $DEBUG; then
                if [ -z "$PKGS" ]; then
                        echo "---- No output." >&2
                else
                        echo "---- Output:" >&2
                        echo "----" $PKGS >&2
                fi
        fi
        if [ -z "$PKGS" ]; then
                break
        fi
        NEW_ARGS=""
        for P in $PKGS; do
                case "$LIST" in
                        *"%${P}%"*)
                                ;;
                        *)
                                LIST="${LIST}${P}%"
                                NEW_ARGS="$NEW_ARGS $P"
                                ;;
                esac
        done
        if [ -z "$NEW_ARGS" ]; then
                break
        fi
        ARGS="$NEW_ARGS"
done

echo -n "${LIST#%}" | tr '%' '\n'
The script is called with either -d or -r, followed by the name of the package. The meaning of the two options is the same as for pkg info, see the pkg-info(8) manual page.
 

Sensucht94

Well-Known Member

Reaction score: 387
Messages: 388

Simple screencast ksh script to record audio/video on FreeBSD using ffmpeg with OSS backend, 60fps, automatic display size adjustment, progressive naming

Code:
#!/usr/bin/env mksh

today="$( date +"%Y%m%d" )"
number=0

while [[ -f $HOME/Video/record_$today$count.mkv ]]
do
    (( ++number ))
    count="$( printf -- '-%02d' "$number" )"
done
fname="$HOME/Video/record_$today$count.mkv"

ffmpeg -y \
    -thread_queue_size 1024 \
    -f oss -i /dev/dsp4 -ac 2 \
    -f x11grab -r 60 \
    -s $(xdpyinfo | grep dimensions | awk '{print $2;}') \
    -i :0.0 -c:v libx264rgb -crf 0 -preset ultrafast -c:a flac \
$fname
 

olli@

Well-Known Member
Developer

Reaction score: 275
Messages: 315

Simple screencast ksh script to record audio/video on FreeBSD using ffmpeg with OSS backend, 60fps, automatic display size adjustment, progressive naming
Just a small note: With a few simple changes, the script would run with FreeBSD's /bin/sh, so people don't have to install an additional shell.
  • Replace #!/usr/bin/env mksh with #!/bin/sh
  • In the “while” line, replace the double brackets with single brackets: [[ ... ]][ ... ]
  • Replace (( ++number )) with : $(( number += 1 )) (note the colon at the beginning!)
Alternatively, I think the script would also run unchanged with bash (except for the “shebang line” at the beginning, of course), which probably most people have installed anyway.
 

aragats

Daemon

Reaction score: 473
Messages: 1,136

In most cases (especially with multi-monitor setup) you want to record only a part of the screen.
Below I added xinput command to get the recording area.
I used left-click for the top-left and right-click for the bottom-right corners. You can use only left-clicks, but will have to uncomment sleep 1 to filter out bouncing.
Also, you'll need to get your pointer device ID (mouse=x) by running xinput --list.
For sake of simlicity I used xinput output directly as bash arrays (it should work in some other shells too), for simple sh you'll have to parse it. (I have to use bash anyway).
Code:
#!/usr/bin/env bash

mouse=6         # get this ID from "xinput --list"
audio=/dev/dsp5
today=$(date +"%Y%m%d")
fname_prefix="/tmp/screen_"
number=0

echo Select top left corner by clicking button 1
while true ; do
    #sleep 1
    eval `xinput --query-state $mouse | grep 'button\|valuator'`
    if [ "down" = "${button[1]}" ] ; then
        X0=${valuator[0]}
        Y0=${valuator[1]}
        break
    fi
done
echo Got: X0=$X0 Y0=$Y0

echo Select bottom right corner by clicking button 3
while true ; do
    #sleep 1
    eval `xinput --query-state $mouse | grep 'button\|valuator'`
    if [ "down" = "${button[3]}" ] ; then
        X1=${valuator[0]}
        Y1=${valuator[1]}
        break
    fi
done
echo Got: X1=$X1 Y1=$Y1

X=$((X1-X0))
Y=$((Y1-Y0))
if [ $X -le 0 ] || [ $Y -le 0 ] ; then
    echo You got negative dimensions: ${X}x${Y}
    exit 1
fi
echo Video size: ${X}x${Y}

while [ -f $fname_prefix$today$count.mkv ]
do
    $((number+=1))
    count=$(printf -- '-%02d' $number)
done
fname="$fname_prefix$today$count.mkv"

ffmpeg -y \
    -thread_queue_size 1024 \
    -f oss -i $audio -ac 2 \
    -f x11grab -r 60 \
    -s ${X}x${Y} \
    -i :0.0+$X0,$Y0 -c:v libx264rgb -crf 0 -preset ultrafast -c:a flac \
    $fname

echo $fname
 

Sensucht94

Well-Known Member

Reaction score: 387
Messages: 388

Just a small note: With a few simple changes, the script would run with FreeBSD's /bin/sh, so people don't have to install an additional shell.
  • Replace #!/usr/bin/env mksh with #!/bin/sh
  • In the “while” line, replace the double brackets with single brackets: [[ ... ]][ ... ]
  • Replace (( ++number )) with : $(( number += 1 )) (note the colon at the beginning!)
Alternatively, I think the script would also run unchanged with bash (except for the “shebang line” at the beginning, of course), which probably most people have installed anyway.
As I've always used ksh as interactive shell, I tend to script on it too (nver used bash or alikes), but I was definitely considering learning sh(1),...thank you for your clarifications, that's good starting point
 

Sensucht94

Well-Known Member

Reaction score: 387
Messages: 388

This is a simple flac2mp3 solution to convert songs recursively in a dir form lossless to mp3 encoding:

Code:
#!/bin/sh

for song in *.flac;
  do title=`echo "${song%.*}"`;
  echo $title;
  ffmpeg -i "$song" "${title}.mp3";
done
While this saves XA_CLIPBOARD content to a dotfile, using xclip(1)
Code:
#!/bin/sh

xclip -o | xclip -sel clip
echo $(xclip -o -sel clip) >> ~/.clipboard
gsed -n '/^\s*$/d; G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P' -i ~/.clipboard

notify-send "'$(xclip -o -sel clip)' saved." &
 

Maxnix

Well-Known Member

Reaction score: 187
Messages: 310

Sensucht94 , you don't need to use echo to assign the song name to the title variable. Just assign like this:
Code:
title="${song%.*}"
The shell will perform the substitution for you. :)
 

mrclksr

Active Member

Reaction score: 108
Messages: 138

Batch-encode all *.wav files in a given directory. Use each wav-file's metadata to create the ID3 tags of the corresponding mp3-file.
Code:
#!/bin/sh

preset="standard"
title_arg="--tt"
album_arg="--tl"
artist_arg="--ta"
date_arg="--ty"
genre_arg="--tg"
track_arg="--tn"
comment_arg="--tc"

usage() {
    echo "Usage: $(basename $0) [-p medium|standard|extreme|insane] dir"
    exit 1
}

while [ $# -gt 0 ]; do
    case "$1" in
    -p)
        preset=$2
        case "$2" in
        medium|standard|extreme|insane)
            preset=$2
            ;;
        *)
            usage
            ;;
        esac
        shift
        ;;
    -*)
        usage
        ;;
    *)
        break
        ;;
    esac
    shift
done

[ $# -lt 1  ] && usage

for cmd in ffprobe lame; do
    if ! which -s $cmd; then
        echo "$cmd not installed"
        exit 1
    fi
done
cd "$1" || exit 1
ls *.wav | while read i; do
    md=$(ffprobe -i "$i" 2>&1);
    args=""
    for k in title album artist genre track date comment; do
        val=$(echo "$md" | awk -v key=$k '{
                regx = sprintf("^[ \t]+%s[ \t]+: ", key);
                n = split($0, a, regx);
                if (n > 1) print a[2];
            }'
        )
        eval $k="\$val"
        eval arg=\${${k}_arg}
        [ -n "$val" ] && args="$args $arg \"$val\""
    done
    eval lame --preset $preset $args \"$i\" \"${i%wav}mp3\"
done
 

roccobaroccoSC

Well-Known Member

Reaction score: 83
Messages: 375

This converts anything to .mp3 (depends on ffmpeg, and also mp3 encoding needs to be enabled when installing the port):
Bash:
% cat `which convertall2mp3 `
#!/bin/bash

find . -name "*.mp4" -exec convert2mp3 -i "{}" -o "{}.mp3" \;
find . -name "*.flv" -exec convert2mp3 -i "{}" -o "{}.mp3" \;
find . -name "*.wmv" -exec convert2mp3 -i "{}" -o "{}.mp3" \;

% cat `which convert2mp3 `   
#!/bin/bash

inputfile="";
outputfile="";
quality="192k";

starttime="";
duration="";

while [ "$1" != "" ]; do

  case $1 in
      "-i" )
          shift;
          inputfile=$1;
          shift;
          ;;
      "-o" )
          shift;
          outputfile=$1;
          shift;
          ;;
      "-q" )
          shift;
          quality=$1;
          shift;
          ;;
      "-ss" )
          shift;
          starttime="-ss $1";
          shift;
          ;;
      "-t" )
          shift;
          duration="-t $1";
          shift;
          ;;
      * )
          echo WARNING: Unknown parameter $1;
          shift;
          ;;
  esac;

done;

if [ "$inputfile" == "" ] || [ "$outputfile" == "" ]; then
  echo Usage: convert2mp3 -i inputfile -o outputfile [-q quality] [-ss starttime] [-t duration];
  echo ...... quality = 128k 160k 96k etc.;
  echo        ss = hh:mm:ss
  echo        t  = hh:mm:ss

else

  echo "Input file: $inputfile";
  echo "Output file: $outputfile";
  echo "Quality: $quality";

#  avconv -i "$inputfile" -acodec libmp3lame -ab $quality -ac 2 -ar 44100 "$outputfile";

  echo ffmpeg $starttime $duration -i "$inputfile" -b:a $quality -vn "$outputfile";
       ffmpeg $starttime $duration -i "$inputfile" -b:a $quality -vn "$outputfile";

fi;
 
Top