Player FM - Internet Radio Done Right
Checked 1M ago
הוסף לפני five שנים
תוכן מסופק על ידי HPR Volunteer and Hacker Public Radio. כל תוכן הפודקאסטים כולל פרקים, גרפיקה ותיאורי פודקאסטים מועלים ומסופקים ישירות על ידי HPR Volunteer and Hacker Public Radio או שותף פלטפורמת הפודקאסט שלהם. אם אתה מאמין שמישהו משתמש ביצירה שלך המוגנת בזכויות יוצרים ללא רשותך, אתה יכול לעקוב אחר התהליך המתואר כאן https://he.player.fm/legal.
Player FM - אפליקציית פודקאסט
התחל במצב לא מקוון עם האפליקציה Player FM !
התחל במצב לא מקוון עם האפליקציה Player FM !
פודקאסטים ששווה להאזין
בחסות
B
Biscuits & Jam


1 Shuai Wang’s Journey from China to Charleston 38:30
38:30
הפעל מאוחר יותר
הפעל מאוחר יותר
רשימות
לייק
אהבתי38:30
Chef Shuai Wang was the runner-up on the 22nd season of Bravo’s Top Chef and is the force behind two standout restaurants in Charleston, South Carolina—Jackrabbit Filly and King BBQ—where he brings together the flavors of his childhood in Beijing and the spirit of the South in some pretty unforgettable ways. He grew up just a short walk from Tiananmen Square, in a tiny home with no electricity or running water, where his grandmother often cooked over charcoal. Later, in Queens, New York, his mom taught herself to cook—her first dishes were a little salty, but they were always made with love. And somewhere along the way, Shuai learned that cooking wasn’t just about food—it was about taking care of people. After years working in New York kitchens, he made his way to Charleston and started building something that feels entirely his own. Today, we’re talking about how all those experiences come together on the plate, the family stories behind his cooking, and what it’s been like to share that journey on national TV. For more info visit: southernliving.com/biscuitsandjam Learn more about your ad choices. Visit podcastchoices.com/adchoices…
HPR2807: Are bash local variables local?
Manage episode 446211223 series 2795599
תוכן מסופק על ידי HPR Volunteer and Hacker Public Radio. כל תוכן הפודקאסטים כולל פרקים, גרפיקה ותיאורי פודקאסטים מועלים ומסופקים ישירות על ידי HPR Volunteer and Hacker Public Radio או שותף פלטפורמת הפודקאסט שלהם. אם אתה מאמין שמישהו משתמש ביצירה שלך המוגנת בזכויות יוצרים ללא רשותך, אתה יכול לעקוב אחר התהליך המתואר כאן https://he.player.fm/legal.
https://en.wikipedia.org/wiki/Scope_%28computer_science%29 In hpr2739, Dave talked briefly about local variables. But what are they? In most modern languages, especially in compiled languages, "local" means that the value of a variable cannot be directly known, by looking up the name, outside the bounds of that function, but that’s not how it works in bash. Languages like C and Python have lexical scope. Lexical scope means local variables are local in the text. The names are local. If I’m writing code that is textually located outside the function, I cannot even describe how to access the variables within the function, because myvariable in my function is not the same variable, not the same place, as myvariable in your function. Languages like Bash and Elisp have dynamic scope. That means local variables are local in time. The names are global. What happens when you declare a variable local in bash is that the existing value of that variable is stowed away, to be brought back when your function exits. #!/usr/bin/env bash function sayscope() { echo The scope is $whatsmyscope } function globalscope() { whatsmyscope=global } function dynamicscope() { whatsmyscope=dynamic } function localscope() { local whatsmyscope=local sayscope dynamicscope sayscope } globalscope sayscope localscope sayscope The scope is global The scope is local The scope is dynamic The scope is global Perl has both, and it calls them local (dynamic scope, like bash) and my (lexical scope): #!/usr/bin/env perl use v5.10; sub sayscope { say "Dynamic scope is $whatsmyscope"; } sub globalscope { $whatsmyscope="global"; } sub dynamicscope { $whatsmyscope="dynamic"; } sub lexicalscope { my $whatsmyscope="lexical"; say "Lexical scope is $whatsmyscope"; sayscope; } sub localscope { local $whatsmyscope="local"; sayscope; dynamicscope; sayscope; lexicalscope; } globalscope; sayscope; localscope; sayscope; Dynamic scope is global Dynamic scope is local Dynamic scope is dynamic Lexical scope is lexical Dynamic scope is dynamic Dynamic scope is global You almost never want to use local in Perl, it’s mostly there for historical reasons — lexical scope is a Perl 5 feature. https://perl.plover.com/local.html covers well the remaining few and narrow exceptions where local might be useful. As dynamic scope has some valid use, it’s available in some otherwise lexically scoped languages. For example, Common LISP has the special form, and several Schemes and Racket have parameter objects: https://www.lispworks.com/documentation/HyperSpec/Body/d_specia.htm https://srfi.schemers.org/srfi-39/srfi-39.html https://docs.racket-lang.org/reference/parameters.html To dig fully into the history and flora of dynamic and lexical scope merits another episode.
…
continue reading
116 פרקים
Manage episode 446211223 series 2795599
תוכן מסופק על ידי HPR Volunteer and Hacker Public Radio. כל תוכן הפודקאסטים כולל פרקים, גרפיקה ותיאורי פודקאסטים מועלים ומסופקים ישירות על ידי HPR Volunteer and Hacker Public Radio או שותף פלטפורמת הפודקאסט שלהם. אם אתה מאמין שמישהו משתמש ביצירה שלך המוגנת בזכויות יוצרים ללא רשותך, אתה יכול לעקוב אחר התהליך המתואר כאן https://he.player.fm/legal.
https://en.wikipedia.org/wiki/Scope_%28computer_science%29 In hpr2739, Dave talked briefly about local variables. But what are they? In most modern languages, especially in compiled languages, "local" means that the value of a variable cannot be directly known, by looking up the name, outside the bounds of that function, but that’s not how it works in bash. Languages like C and Python have lexical scope. Lexical scope means local variables are local in the text. The names are local. If I’m writing code that is textually located outside the function, I cannot even describe how to access the variables within the function, because myvariable in my function is not the same variable, not the same place, as myvariable in your function. Languages like Bash and Elisp have dynamic scope. That means local variables are local in time. The names are global. What happens when you declare a variable local in bash is that the existing value of that variable is stowed away, to be brought back when your function exits. #!/usr/bin/env bash function sayscope() { echo The scope is $whatsmyscope } function globalscope() { whatsmyscope=global } function dynamicscope() { whatsmyscope=dynamic } function localscope() { local whatsmyscope=local sayscope dynamicscope sayscope } globalscope sayscope localscope sayscope The scope is global The scope is local The scope is dynamic The scope is global Perl has both, and it calls them local (dynamic scope, like bash) and my (lexical scope): #!/usr/bin/env perl use v5.10; sub sayscope { say "Dynamic scope is $whatsmyscope"; } sub globalscope { $whatsmyscope="global"; } sub dynamicscope { $whatsmyscope="dynamic"; } sub lexicalscope { my $whatsmyscope="lexical"; say "Lexical scope is $whatsmyscope"; sayscope; } sub localscope { local $whatsmyscope="local"; sayscope; dynamicscope; sayscope; lexicalscope; } globalscope; sayscope; localscope; sayscope; Dynamic scope is global Dynamic scope is local Dynamic scope is dynamic Lexical scope is lexical Dynamic scope is dynamic Dynamic scope is global You almost never want to use local in Perl, it’s mostly there for historical reasons — lexical scope is a Perl 5 feature. https://perl.plover.com/local.html covers well the remaining few and narrow exceptions where local might be useful. As dynamic scope has some valid use, it’s available in some otherwise lexically scoped languages. For example, Common LISP has the special form, and several Schemes and Racket have parameter objects: https://www.lispworks.com/documentation/HyperSpec/Body/d_specia.htm https://srfi.schemers.org/srfi-39/srfi-39.html https://docs.racket-lang.org/reference/parameters.html To dig fully into the history and flora of dynamic and lexical scope merits another episode.
…
continue reading
116 פרקים
Alle episoder
×This show has been flagged as Explicit by the host. hajime This installation script installs an Arch Linux system on an x64 architecture. The installation can be done with or without a network connection (internet). oxo/hajime - Codeberg.org hajime/make-recov at main - oxo/hajime - Codeberg.org isolatest/isolatest at main - oxo/isolatest - Codeberg.org Provide feedback on this episode .…
This show has been flagged as Explicit by the host. font selection Nerd Fonts - Iconic font aggregator, glyphs/icons collection, & fonts patcher Programming Fonts - Test Drive font installation install font package % yay -Sy $font_package update font database % fc-cache --force --verbose verify available fonts % fc-list | grep $font_name change font in application configs e.g.: alacritty emacs sway tofi Provide feedback on this episode .…
This show has been flagged as Explicit by the host. In today's show, oxo show us how you can use the output of the find command with -print0 option to rsync files to another location. find . -type f -mmin -230 -print0 | rsync -aAXv --info=progress2,stats --progress --from0 --files-from - . dst Provide feedback on this episode .…
This show has been flagged as Explicit by the host. Hi listener! My name is oxo. In this first episode for HPR I will introduce myself a little and present my plans for my future episodes on this channel. My goal is to let you as a listener follow along while I am learning new interesting things about Linux. This will be mainly about how I manage to survive the commandline while having fun doing so! :) My main codebase is in the codeberg repository, which you can find here: oxo - Codeberg.org Comments are always welcome! Please contact me via Mastodon: @oxo@qoto.org or email oxo at protonmail.com Provide feedback on this episode .…
This show has been flagged as Clean by the host. Make a diff: $ diff --unified --new-file --recursive original/ my-revision/ > my.patch Send my.patch to somebody so they can use it as input for the patch command: $ patch --strip 0 < my.patch Provide feedback on this episode .
This show has been flagged as Clean by the host. Today I Learnt more Bash tips Sgoti talks about supplying options to bash scripts Tags: Bash tips, TIL, getopts #!/bin/bash # License: GPL v3 # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . #Name: showtime.sh #Purpose: Time to make a show. #Version: beta 0.01 #Author: SGOTI (Some Guy On The Internet) #Date: 2023-12-29 #variables: bindir=/usr/bin/ cat=${bindir}cat date=${bindir}date echo=${bindir}echo mkdir=${bindir}mkdir dirshow0=${HOME}/Music/hpr/shows dirshow1=${dirshow0}/$(${date} +%Y) dirqueue=${dirshow1}/queue/$(${date} +%F) dirreserve=${dirshow1}/reserve-queue/$(${date} +%F) #start: function help() { ${cat} << EOH Usage: $0 [-s] [-r] [-q] [-h] name-of-show -s (Regular queue) -r (Reserve queue) -q (quit) -h (help) Examples: $0 -s name-of-show $0 -r name-of-show $0 -q $0 -h EOH } ## Use `getopts` to read user option into script. ## while getopts ":s:r:q:h" option; do case $option in s) show=$OPTARG function mkq () { ${mkdir} -v -p ${dirqueue}/${show}/edit; ${mkdir} -v -p ${dirqueue}/${show}/prod; ${cat} > ${dirqueue}/${show}/edit/${show}.md << _EOD_ # ${show} # ## subtitle ## - Tags: This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/ "CC-BY-SA 4.0 International"). _EOD_ builtin pushd -n ${dirqueue}/${show}/edit; builtin pushd -n ${dirqueue}/${show}/prod; } if [ -d ${dirshow1} ]; then mkq else ${echo} "Good Heavens! It's a new year."; ${mkdir} -v -p ${dirshow1}; mkq fi ;; r) reserve=$OPTARG function mkr () { ${mkdir} -v -p ${dirreserve}/${reserve}/edit; ${mkdir} -v -p ${dirreserve}/${reserve}/prod; ${cat} > ${dirreserve}/${reserve}/edit/${reserve}.md << _EOD_ # ${reserve} # ## subtitle ## - Tags: This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/ "CC-BY-SA 4.0 International"). _EOD_ builtin pushd -n ${dirreserve}/${reserve}/edit; builtin pushd -n ${dirreserve}/${reserve}/prod; } if [ -d ${dirshow1} ]; then mkr else ${echo} "Good Heavens! It's a new year."; ${mkdir} -v -p ${dirshow1}; mkr fi ;; q) ${echo} "Goodbye."; exit ;; h) help exit ;; *) if [ -z "${option}" ]; then help exit 1 fi ${echo} "Good Heavens! Invalid input."; help exit ;; esac done exit; #!/bin/bash # License: GPL v3 # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . #Name: sc.sh #Purpose: #Version: beta 0.01 #Author: SGOTI (Some Guy On The Internet) #Date: 2023-12-31 #variables: bindir=/usr/bin/ cat=${bindir}cat date=${bindir}date echo=${bindir}echo ls=${bindir}ls screen=${bindir}screen #start: ${echo} -e "\nStep 0: $(${date} +%F), $(${date} +%T)"; function help() { ${cat} << EOH Usage: $0 [-b] [-s] [-k] [-h] name-of-show -b [y|n] (Create or kill, base sockets.) -s (Create new sockets.) -k (Kill sockets.) -h (help menu) Examples: $0 -b y $0 -b n $0 -s name-of-socket $0 -k name-of-socket $0 -h EOH } ${echo} -e "\nStep 1: $(${date} +%F), $(${date} +%T)"; while getopts ":b:s:k:h:" option; do case "${option}" in b) userinput0=$OPTARG if [ ${userinput0} == "y" ]; then ${screen} -dmS apps; ${screen} -dmS jobby; ${screen} -ls; elif [ ${userinput0} == "n" ]; then # You don't need the entire name to kill the socket. ${screen} -X -S "app" kill ${screen} -X -S "job" kill ${screen} -ls; else ${echo} "Good Heavens!" ${screen} -ls; help exit 1 fi ;; s) userinput0=$OPTARG ${screen} -dmS "${userinput0}"; clear ${screen} -ls; ${echo} -e "\nNew sockets: $(${date} +%F), $(${date} +%T)"; ;; k) userinput0=$OPTARG ${screen} -XS ${userinput0} kill clear ${screen} -ls; ${echo} -e "\nKill sockets: $(${date} +%F), $(${date} +%T)"; ;; h) help ${echo} -e "\nHelp menu: $(${date} +%F), $(${date} +%T)"; exit ;; *) if [ -z "${option}" ]; then help exit 1 fi ${echo} "Good Heavens! Invalid input."; help exit ;; esac done ${echo} -e "\nStep 2: $(${date} +%F), $(${date} +%T)"; exit; Source: In-Depth Series: Today I Learnt Source: In-Depth Series: Bash Scripting This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License . Provide feedback on this episode .…
This show has been flagged as Explicit by the host. Overview Recently Ken Fallon did a show on HPR, number 3962 , in which he used a Bash pipeline of multiple commands feeding their output into a while loop. In the loop he processed the lines produced by the pipeline and used what he found to download audio files belonging to a series with wget . This was a great show and contained some excellent advice, but the use of the format: pipeline | while read variable; do ... reminded me of the "gotcha" I mentioned in my own show 2699 . I thought it might be a good time to revisit this subject. So, what's the problem? The problem can be summarised as a side effect of pipelines. What are pipelines? Pipelines are an amazingly useful feature of Bash (and other shells). The general format is: command1 | command2 ... Here command1 runs in a subshell and produces output (on its standard output ) which is connected via the pipe symbol ( | ) to command2 where it becomes its standard input . Many commands can be linked together in this way to achieve some powerful combined effects. A very simple example of a pipeline might be: $ printf 'World\nHello\n' | sort Hello World The printf command (≡ 'command1' ) writes two lines (separated by newlines) on standard output and this is passed to the sort command's standard input (≡ 'command2' ) which then sorts these lines alphabetically. Commands in the pipeline can be more complex than this, and in the case we are discussing we can include a loop command such as while . For example: $ printf 'World\nHello\n' | sort | while read line; do echo "($line)"; done (Hello) (World) Here, each line output by the sort command is read into the variable line in the while loop and is written out enclosed in parentheses. Note that the loop is written on one line. The semi-colons are used instead of the equivalent newlines. Variables and subshells What if the lines output by the loop need to be numbered? $ i=0; printf 'World\nHello\n' | sort | while read line; do ((i++)); echo "$i) $line"; done 1) Hello 2) World Here the variable 'i' is set to zero before the pipeline. It could have been done on the line before of course. In the while loop the variable is incremented on each iteration and included in the output. You might expect 'i' to be 2 once the loop exits but it is not. It will be zero in fact. The reason is that there are two 'i' variables. One is created when it's set to zero at the start before the pipeline. The other one is created in the loop as a "clone". The expression: ((i++)) both creates the variable (where it is a copy of the one in the parent shell) and increments it. When the subshell in which the loop runs completes, it will delete this version of 'i' and the original one will simply contain the zero that it was originally set to. You can see what happens in this slightly different example: $ i=1; printf 'World\nHello\n' | sort | while read line; do ((i++)); echo "$i) $line"; done 2) Hello 3) World $ echo $i 1 These examples are fine, assuming the contents of variable 'i' incremented in the loop are not needed outside it. The thing to remember is that the same variable name used in a subshell is a different variable; it is initialised with the value of the "parent" variable but any changes are not passed back. How to avoid the loss of changes in the loop To solve this the loop needs to be run in the original shell, not a subshell. The pipeline which is being read needs to be attached to the loop in a different way: $ i=0; while read line; do ((i++)); echo "$i) $line"; done < <(printf 'World\nHello\n' | sort) 1) Hello 2) World $ echo $i 2 What is being used here is process substitution . A list of commands or pipelines are enclosed with parentheses and a 'less than' sign prepended to the list (with no intervening spaces). This is functionally equivalent to a (temporary) file of data. The redirection feature allows for data being read from a file in a loop. The general format of the command is: while read variable do # Use the variable done < file Using process substitution instead of a file will achieve what is required if computations are being done in the loop and the results are wanted after it has finished. Beware of this type of construct The following one-line command sequence looks similar to the version using process substitution, but is just another form of pipeline: $ i=0; while read line; do echo $line; ((i++)); done < /etc/passwd | head -n 5; echo $i root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync 0 This will display the first 5 lines of the file but does it by reading and writing the entire file and only showing the first 5 lines of what is written by the loop. What is more, because the while is in a subshell in a pipeline changes to variable 'i' will be lost. Advice Use the pipe-connected-to-loop layout if you're aware of the pitfalls, but will not be affected by them. Use the read-from-process-substitution format if you want your loop to be complex and to read and write variables in the script. Personally, I always use the second form in scripts, but if I'm writing a temporary one-line thing on the command line I usually use the first form. Tracing pipelines (advanced) I have always wondered about processes in Unix. The process you log in to, normally called a shell runs a command language interpreter that executes commands read from the standard input or from a file. There are several such interpreters available, but we're dealing with bash here. Processes are fairly lightweight entities in Unix/Linux. They can be created and destroyed quickly, with minimal overhead. I used to work with Digital Equipment Corporation's OpenVMS operating system which also uses processes - but these are much more expensive to create and destroy, and therefore slow and less readily used! Bash pipelines, as discussed, use subshells . The description in the Bash man page says: Each command in a multi-command pipeline, where pipes are created, is executed in a subshell, which is a separate process. So a subshell in this context is basically another child process of the main login process (or other parent process), running Bash. Processes (subshells) can be created in other ways. One is to place a collection of commands in parentheses. These can be simple Bash commands, separated by semi-colons, or pipelines. For example: $ (echo "World"; echo "Hello") | sort Hello World Here the strings "World" and "Hello" , each followed by a newline are created in a subshell and written to standard output. These strings are piped to sort and the end result is as shown. Note that this is different from this example: $ echo "World"; echo "Hello" | sort World Hello In this case "World" is written in a separate command, then "Hello" is written to a pipeline. All sort sees is the output from the second echo , which explains the output. Each process has a unique numeric id value (the process id or PID ). These can be seen with tools like ps or htop . Each process holds its own PID in a Bash variable called BASHPID . Knowing all of this I decided to modify Ken's script from show 3962 to show the processes being created - mainly for my interest, to get a better understanding of how Bash works. I am including it here in case it may be of interest to others. #!/bin/bash series_url="https://hackerpublicradio.org/hpr_mp3_rss.php?series=42&full=1&gomax=1" download_dir="./" pidfile="/tmp/hpr3962.sh.out" count=0 echo "Starting PID is $BASHPID" > $pidfile (echo "[1] $BASHPID" >> "$pidfile"; wget -q "${series_url}" -O -) |\ (echo "[2] $BASHPID" >> "$pidfile"; xmlstarlet sel -T -t -m 'rss/channel/item' -v 'concat(enclosure/@url, "→", title)' -n -) |\ (echo "[3] $BASHPID" >> "$pidfile"; sort) |\ while read -r episode; do [ $count -le 1 ] && echo "[4] $BASHPID" >> "$pidfile" ((count++)) url="$( echo "${episode}" | awk -F '→' '{print $1}' )" ext="$( basename "${url}" )" title="$( echo "${episode}" | awk -F '→' '{print $2}' | sed -e 's/[^A-Za-z0-9]/_/g' )" #wget "${url}" -O "${download_dir}/${title}.${ext}" done echo "Final value of \$count = $count" echo "Run 'cat $pidfile' to see the PID numbers" The point of doing this is to get information about the pipeline which feeds data into the while loop . I kept the rest intact but commented out the wget command. For each component of the pipeline I added an echo command and enclosed it and the original command in parentheses, thus making a multi-command process. The echo commands write a fixed number so you can tell which one is being executed, and it also writes the contents of BASHPID . The whole thing writes to a temporary file /tmp/hpr3962.sh.out which can be examined once the script has finished. When the script is run it writes the following: $ ./hpr3962.sh Final value of $count = 0 Run 'cat /tmp/hpr3962.sh.out' to see the PID numbers The file mentioned contains: Starting PID is 80255 [1] 80256 [2] 80257 [3] 80258 [4] 80259 [4] 80259 Note that the PID values are incremental. There is no guarantee that this will be so. It will depend on whatever else the machine is doing. Message number 4 is the same for every loop iteration, so I stopped it being written after two instances. The initial PID is the process running the script, not the login (parent) PID. You can see that each command in the pipeline runs in a separate process ( subshell ), including the loop. Given that a standard pipeline generates a process per command, I was slightly surprised that the PID numbers were consecutive. It seems that Bash optimises things so that only one process is run for each element of the pipe. I expect that it would be possible for more processes to be created by having pipelines within these parenthesised lists, but I haven't tried it! I found this test script quite revealing. I hope you find it useful too. Links Bash pipelines: GNU Bash manual: 3.2.3 Pipelines Bash loops: GNU Bash manual: 3.2.5.1 Looping Constructs Bash process substitution: GNU Bash manual: 3.5.6 Process Substitution HPR shows referenced: hpr2045 :: Some other Bash tips hpr2699 :: Bash Tips - 15 hpr3962 :: It's your data Provide feedback on this episode .…
This show has been flagged as Clean by the host. This is a response show to hpr3959 :: Download any HPR series with english file names "A dir with the series name will be created and all shows will be renamed to ShowTitle.mp3 inside it" This was the first show by gemlog and he used Bash, sed, grep, wget, to scrape the HPR site. This is great but as he points out any change to the site will break the script. A safer way to get the episodes is by scraping the rss feed, and the following is an example of how you might do that #!/bin/bash series_url="https://hackerpublicradio.org/hpr_mp3_rss.php?series=42&full=1&gomax=1" download_dir="./" wget "${series_url}" -O - | xmlstarlet sel -T -t -m 'rss/channel/item' -v 'concat(enclosure/@url, "→", title)' -n - | sort | while read episode do url="$( echo ${episode} | awk -F '→' '{print $1}' )" ext="$( basename "${url}" )" title="$( echo ${episode} | awk -F '→' '{print $2}' | sed -e 's/[^A-Za-z0-9]/_/g' )" wget "${url}" -O "${download_dir}/${title}.${ext}" done Provide feedback on this episode .…
This show has been flagged as Explicit by the host. Hello all. This is gemlog from Terrace, bc, canada just up near the alaska panhandle. Some of you may know me from in COM chat on sdf dot org or as a fedizen on the tilde dot zone instance of mastodon. Now, the other day I finally got around to checking out HPR properly, even though my masto-pal claw-dio-m turned me on to it a couple of years ago. Recently, on a friday night in irc on tilde radio, I noticed there were whole series on hpr and not only single shows and that got me kind of excited. I guess I'm easily excitable. Anyhow, something I could listen to at work or while driving. Still, I managed to forget about it until /just/ before I was leaving the house for work on Monday morning. I rushed to copy over a few shows - nearly at random onto my phone and headed out to work. After I got my morning sorted at work, I told VLC to play-all and enjoyed a couple of shows. I noticed that each show I had chosen had a beg post at the beginning. I figured I could make one on at least something from my messy gemlog/bin dir. However, after a break, I came back and couldn't remember which 4 digit numbered dot mp3 I had finished up on, which mildly irked me. Well, as we all know, irk becomes itch and I put my sad regex skills to the test scraping the hpr website with a custom bash script later when I got home. A very custom bash script. Like all scrapers, if any of the guys at hpr even breathe the wrong way, it will probably break horribly. On the other hand, I've had scrapers that looked just as sad running for many years against a canadian government site. So. Who knows? All the script uses are some built-ins from bash along with sed and wget for the actual getting. My local instance of searX N G was left smoking as scrambled for sed incantations to string together. I'm not a sed guy. Usage is simple, as the script only accepts one argument: ... the four digit series number of the show you want to download. It will create a dir with the series name and download every mp3 it finds, renaming each show to the show title. I was tempted to doll it up with some niceties like options for download dir, a selector for a series with a dialog of some kind... yada yada yada. But... we all know what happens when you stretch a quick hack with a bash script too far for the scripting language: hours of misery wishing you'd started with some other language. So far, I've used the script to download 8 series. DU dash S H tells me they add up to 2 dot 2 gig, so it seems to work well enough. It comes with the same iron clad warranty as everything I write: If it breaks, you get to keep all the pieces. Thanks for listening. #!/bin/bash # gemlog@gemlog.ca 2023-08-26 # License: CC BY-SA 4.0. # not proud of my continuing lack of regex foo frankly... if [ $# -lt 1 ]; then echo 1>&2 "$0: You need to enter the HPR Series Number to download as 4 digits" echo "The full list of HPR Series is at https://hackerpublicradio.org/series/index.html " exit 2 fi snumber=$1 re='^[[:digit:]]{4}$' if [[ $snumber =~ $re ]]; then wget https://hackerpublicradio.org/series/$snumber.html -q -O /tmp/$snumber.html content=$(]*>//g;/]*>//g;/]*>//g;/ Provide feedback on this episode .…
This show has been flagged as Explicit by the host. HPR Shows by Klaatu. Source: hpr3887 :: 10 must-know commands for a new cloud admin. Source: hpr3882 :: Alternatives to the cd command. Hot sauce lady. Source: Franks Red Hot Queen 2011. pwd && ls --group-directories-first --classify --almost-all # some more ls aliases alias la='ls -l --human-readable --group-directories-first --classify --almost-all' alias ll='ls --group-directories-first --classify --almost-all' alias lr='ls -l --human-readable --group-directories-first --classify --recursive' alias lar='ls -l --human-readable --group-directories-first --classify --almost-all --recursive' alias lap='ls -l --human-readable --group-directories-first --classify --almost-all | less' # safety first ;) alias rmi='rm --interactive --verbose' alias mvi='mv --interactive --verbose' alias cpi='cp --interactive --verbose' alias .shred='bleachbit --shred' # cd multi dir alias ..='cd ..;' alias .2='cd ../..;' alias .3='cd ../../..;' alias .4='cd ../../../..;' alias .5='cd ../../../../..;' # Directory controls. function cd () { clear; builtin cd "$@" && ls --group-directories-first --classify --almost-all; history -w; } #function pp () { #builtin pushd +$@ && ls --group-directories-first --classify --almost-all #} function pushup (){ builtin pushd $HOME/.config/vim/sessions/ builtin pushd $HOME/.local/bin/ builtin pushd $HOME/.thunderbird/*.default-release/ builtin pushd $HOME/Documents/non-of-your-business/ builtin pushd $HOME/Downloads/in/ builtin pushd $HOME/Downloads/out/ builtin pushd $HOME/Downloads/playground/ builtin pushd $HOME/Music/hpr/shows/ builtin pushd $HOME/projects/ builtin pushd $HOME/projects/hprbank/bp/ builtin pushd $HOME/symlinks/ builtin pushd $HOME/tmp/ builtin pushd +11 builtin dirs -v } alias pd='pushd' alias dirs='dirs -v' # Update alias .upg='sudo apt update && sudo apt upgrade -y;' # shutdown | reboot alias .sd='sudo shutdown -P now;' alias .rs='sudo reboot;' # Misc alias ccb='cat $HOME/cb | xsel --input --clipboard && echo "Copy. $(date "+%F %T")";' alias pcb='xsel --output --clipboard > $HOME/cb && echo "Copy. $(date "+%F %T")";' alias zz='xsel -c -b && echo "Clipboard Cleared. $(date "+%F %T")";' # File Mods alias 700='chmod --verbose =700' alias 600='chmod --verbose =600' alias 400='chmod --verbose =400' ############################################################################### # Functions ############################################################################### function .s () { ln --symbolic --verbose --target-directory=$HOME/symlinks/ $(pwd)/${1}; } function extract () { if [ -f $1 ] then case $1 in *.tar.bz2) tar -vxjf $1 ;; *.tar.gz) tar -vxzf $1 ;; *.tar) tar -xvf $1 ;; *.bz2) bunzip2 $1 ;; *.rar) unrar -x $1 ;; *.gz) gunzip $1 ;; *.tar) tar -vxf $1 ;; *.tbz2) tar -vxjf $1 ;; *.tgz) tar -vxzf $1 ;; *.zip) unzip $1 ;; *.Z) uncompress $1 ;; *.7z) 7z -x $1 ;; *) echo "Good Heavens, '$1' will NOT extract..." ;; esac else echo "Good Heavens, '$1' is NOT a valid file." fi } function myip () { ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/'; } function .mkd (){ mkdir -v $(date +%F) && pushd $(date +%F); } function .mkt (){ tmpdir=$(mktemp -d /tmp/$(date +%F).XXXXXXXX) && pushd ${tmpdir} } function .d (){ echo $(date +%F)$1 | xsel -i -b; } function .sh () { NEWSCRIPT=${1}.sh cat >> ${NEWSCRIPT} << EOS #!/bin/bash # License: GPL v3 # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . #Name: ${NEWSCRIPT} #Purpose: #Version: beta 0.01 #Author: SGOTI (Some Guy On The Internet) #Date: $(date +%F) #variables: #start: exit; EOS if [ -f "${NEWSCRIPT}" ] then chmod 700 ${NEWSCRIPT} else echo "Good Heavens! There isn't a "${NEWSCRIPT}"" fi } function .fmd () { xsel -o -b | fmt -w 76 | sed 's/$/ /g s/ / /g s/ / /g s/ / /g s/$/ /g s/ *$/ /g s/ / /g' | xsel -i -b; } #!/bin/bash # License: GPL v3 # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . #Name: bfn.sh #Purpose: Create better file names. #Version: beta 0.01 #Author: SGOTI (Some Guy On The Internet) #Date: 2022-11-08 #variables: oldname=$(echo ${1%.*}) newname=$(echo $oldname | sed 's/ /-/g;s/_/-/g;s/./-/g;s/--*/-/g;/\/d' | tr [:upper:] [:lower:]) ext1=".$(echo ${1##*.})" ext2=".$(echo ${1##*.} | tr [:upper:] [:lower:])" #start: function bcase () { if [ -f $1 ] then echo -e "renaming $oldnamen"; mv -v "$oldname$ext1" "$newname$ext2"; else mv -v "$oldname" "$newname"; fi } bcase exit; #!/bin/bash # License: GPL v3 # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . #Name: perm.sh #Purpose: #Version: beta 0.01 #Author: SGOTI (Some Guy On The Internet) #Date: 2023-01-13 #variables: var_dir=${1} #start: function bfp () { find "${var_dir}" -type d -exec chmod -R =700 {} + find "${var_dir}" -type f -exec chmod -R =600 {} + } bfp exit; This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License . Provide feedback on this episode .…
Five or six ways I could think of to roam the files of your Linux computer without cd. pushd and popd dirs https://en.wikipedia.org/wiki/Pushd_and_popd The pushd command, when called with a filepath as an argument, saves the current working directory in memory (via a directory stack) so it can be returned to at any time, places the new filepath at the top of the stack, and changes to the new filepath. The popd command returns to the path at the top of the directory stack. cd - From man bash An argument of - is converted to $OLDPWD before the directory change is attempted. Variables EXPORT mydir="/path/to/file/" cd ${mydir} History and histverify Using !number from the history command will execute the command [user@pc ~]$ history 1 cd tmp 2 cd ~ 3 history [user@pc ~]$ !3 cd tmp [user@pc tmp]$ from the man command shopt [-pqsu] [-o] [optname ...] Toggle the values of settings controlling optional shell behavior. ... -s Enable (set) each optname. -u Disable (unset) each optname. Now using !number from the history command will put the command on the prompt but you need to execute it yourself [user@pc ~]$ shopt -s histverify [user@pc ~]$ !39673 [user@pc ~]$ cd tmp autocd command [ken@kalani ~]$ shopt -s autocd [ken@kalani ~]$ tmp cd -- tmp [ken@kalani tmp]$ ~ cd -- /home/ken working without changing to directory [ken@kalani ~]$ ls tmp…
A named pipe is like a UNIX pipe, except it takes the form of a file. $ mkfifo mypipe $ echo "Hacker Public Radio" > mypipe & $ cat mypipe Hacker Public Radio
Overview Have you ever written a Bash script (or any shell script) where you generate a message like 'Found 42 files' and the day comes when it reports 'Found 1 files'? Have you been irritated by this? I have, and I go to lengths to deal properly with (English) plurals in my Bash scripts. Method 1 The simplest solution would be to use an 'if' statement: if [[ $fcount -eq 1 ]]; then echo "Found 1 file" else echo "Found $fcount files" fi This works, but to have to do it for every message would be a pain! Method 2 The next approach to this problem might be to write a Bash function. pluralise () { local singular="${1}" local plural="${2}" local count="${3}" if [[ $count -eq 1 ]]; then echo "$singular" else echo "$plural" fi } This can be called as follows: $ i=1; echo "Found $i $(pluralise "file" "files" $i)" Found 1 file $ i=42; echo "Found $i $(pluralise "file" "files" $i)" Found 42 files The string being displayed with echo contains a command substitution ('$(command)') which returns 'file' or 'files' depending on the value given. The first two arguments can be more complex than plain strings: $ i=1; echo "There $(pluralise "is 1 light" "are $i lights" $i)" There is 1 light $ i=4; echo "There $(pluralise "is 1 light" "are $i lights" $i)" There are 4 lights The pluralise function is available for download. Method 3 The GNU project has developed a set of utilities called the GNU gettext utilities consisting of tools and documentation for translation. This is a large subject which is not suitable for a short HPR episode such as this one. Among the tools is 'ngettext' which performs the function we have been discussing - choosing among plural forms. It also implements translations if desired (and translation files are provided as part of the software being developed). We will not discuss the translation topic here, but the choice of plurals is something that can be used in Bash scripts. The 'ngettext' tool takes three mandatory parameters: MSGID - the singular form of the text MSGID-PLURAL - the plural form of the text COUNT - the value used to make the singular/plural choice There are other optional parameters and options but they are not relevant here. The tool can be used in exactly the same way as the 'pluralise' example above. $ i=1; echo "There $(ngettext "is 1 light" "are $i lights" $i)" There is 1 light $ i=4; echo "There $(ngettext "is 1 light" "are $i lights" $i)" There are 4 lights Whether you use this or a Bash function is your choice. Conclusion I have been using ngettext in my scripts since I discovered it. If you also need to provide messages in your projects in other languages then this might be a good idea. I admit that my understanding of the GNU gettext project is superficial, so, on reflection it might be better to use a Bash function, since I don’t currently need all of the features GNU gettext provides. Links…
Preamble This is a case where I came upon a thing in Bash I had never considered before and was pleased and surprised that there was a way of doing what I wanted to do! If this is completely obvious to you, apologies, but it wasn’t to me! Overview Many programming languages have the concept of short-circuit evaluation in Boolean expressions. What this means is that in an expression such as: A AND B if A is false then the whole expression must be false, and B doesn’t have to be evaluated. That is because both arguments to AND have to be true for the overall result to be true. If A is true on the other hand, then B has to be evaluated to determine if the overall result is true. Similarly with: A OR B if A is true then the whole expression must be true and B can be skipped without evaluation. This is because only one argument to OR needs to be true to return a true result. If A is false on the other hand, then B has to be evaluated to determine if the overall result is false. Both of these expressions are evaluated from left to right. This is not a given in all languages. Some use special operators such as 'and_then' and 'or_else' which explicitly perform short-circuiting and left-to-right evaluation. Definition In simple terms, short-circuiting is where the evaluation of an expression is stopped as soon as its outcome is determined. The Wikipedia article Short-circuit evaluation defines it as: Short-circuit evaluation, minimal evaluation, or McCarthy evaluation (after John McCarthy) is the semantics of some Boolean operators in some programming languages in which the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression: when the first argument of the AND function evaluates to false, the overall value must be false; and when the first argument of the OR function evaluates to true, the overall value must be true. This article contains a table entitled Boolean operators in various languages which shows details of how various programming and scripting languages cater for this feature. Use case I was writing a Bash script in which I wanted to ask questions about various steps - should they be done or not? Alternatively, I wanted to be able to set an option to run without interaction and assume the answer is 'yes' to all questions. I’d encountered short-circuit evaluation before in Pascal and Perl so I wondered if I could use it in Bash. The expression I was trying to write was: if [[ $YES -eq 1 ]] || yes_no 'Create directory? %s ' 'N'; then # Create directory fi Variable YES is being set through an option '-Y'; it’s normally set to zero but is set to 1 if the option is used. yes_no is a function I wrote, and talked about in HPR episode 2096: “Useful Bash functions - part 2”. The requirement was that if YES was set to 1 I didn’t want the function…
Carl talks about a method to move function definitions to the bottom of a script using sed: #!/bin/sh source <(sed '1,/^exit/ d' $0) __say "hello" exit __say() { echo $1 } Guest Host #1 (scroll to the bottom to ruin the surprise) talks about the shift command using this example: startdate="$1" # Pick up date shift days=0 # Loop through args and create events while [ $1 ] ; do # as many times as you add a timestamp [ $1 != "off" ] && khal new $(date -j -v+"$days"d -f %Y-%m-%d +%Y-%m-%d $startdate) $1 8H Work let days++ shift done Guest Host #2 provides tips and examples on how to use variables safely and politely provide default values. One example of assigning a default value is: foo=${foo:-"blah"} Carl then closes out with the : (colon) shell builtin and provides a variation on the above default value: : ${foo:="blah"}…
H
Hacker Public Radio

Extra ancillary Bash tips - 13 Making decisions in Bash This is the thirteenth episode in the Bash Tips sub-series. It is the fifth and final of a group of shows about making decisions in Bash. In the last four episodes we saw the types of test Bash provides, and we looked briefly at some of the commands that use these tests. We looked at conditional expressions and all of the operators Bash provides to do this. We concentrated particularly on string comparisons which use glob and extended glob patterns then we devoted an episode to Bash regular expressions. Now we want to look at the final topic within regular expressions, the use of capture groups. Long notes I have provided detailed notes as usual for this episode, and these can be viewed here. Links "GNU BASH Reference Manual" "Bash Conditional Constructs" "Bash Conditional Expressions" "Bourne Shell Builtins" "The set Builtin" "Bash Pattern Matching" "POSIX Shell Command Language" - documentation of all of the POSIX features mentioned in this series. HPR series: Bash Scripting Previous episodes under the heading Bash Tips: HPR episode 1648 "Bash parameter manipulation" HPR episode 1843 "Some Bash tips" HPR episode 1884 "Some more Bash tips" HPR episode 1903 "Some further Bash tips" HPR episode 1951 "Some additional Bash tips" HPR episode 2045 "Some other Bash tips" HPR episode 2278 "Some supplementary Bash tips" HPR episode 2293 "More supplementary Bash tips" HPR episode 2639 "Some ancillary Bash tips - 9" HPR episode 2649 "More ancillary Bash tips - 10" HPR episode 2659 "Further ancillary Bash tips - 11" HPR episode 2669 "Additional ancillary Bash tips - 12" Resources: Examples: bash13_ex1.sh, bash13_ex2.sh, bash13_ex3.sh, bash13_ex4.sh, bash13_ex4.txt…
H
Hacker Public Radio

Additional ancillary Bash tips - 12 Making decisions in Bash This is the twelfth episode in the Bash Tips sub-series. It is the fourth of a group of shows about making decisions in Bash. In the last three episodes we saw the types of test Bash provides, and we looked briefly at some of the commands that use these tests. We looked at conditional expressions and all of the operators Bash provides to do this. We concentrated particularly on string comparisons which use glob and extended glob patterns. Now we want to look at the other form of string comparison, using regular expressions. Long notes I have provided detailed notes as usual for this episode, and these can be viewed here. Links "GNU BASH Reference Manual" "Bash Conditional Constructs" "Bash Conditional Expressions" "Bourne Shell Builtins" "Bash Pattern Matching" "POSIX Shell Command Language" - documentation of all of the POSIX features mentioned in this series. "Extended Regular Expressions" "A Brief Introduction to Regular Expressions" HPR series: Bash Scripting Previous episodes under the heading Bash Tips: HPR episode 1648 "Bash parameter manipulation" HPR episode 1843 "Some Bash tips" HPR episode 1884 "Some more Bash tips" HPR episode 1903 "Some further Bash tips" HPR episode 1951 "Some additional Bash tips" HPR episode 2045 "Some other Bash tips" HPR episode 2278 "Some supplementary Bash tips" HPR episode 2293 "More supplementary Bash tips" HPR episode 2639 "Some ancillary Bash tips - 9" HPR episode 2649 "More ancillary Bash tips - 10" HPR episode 2659 "Further ancillary Bash tips - 11" Resources: Examples: bash12_ex1.sh, bash12_ex2.sh, bash12_ex3.sh, bash12_ex4.sh, bash12_ex5.sh…
H
Hacker Public Radio

Further ancillary Bash tips - 11 This is the eleventh episode in the Bash Tips sub-series. It is the third of a group of shows about making decisions in Bash. In the last two episodes we saw the types of test Bash provides, and we looked briefly at some of the commands that use these tests. Now we want to start examining the expressions that can be used in these tests, and how to combine them. We will also start looking at string comparisons in extended tests. Long notes I have provided detailed notes as usual for this episode, and these can be viewed here. Links "GNU BASH Reference Manual" "Bash Conditional Constructs" "Bash Conditional Expressions" "Bourne Shell Builtins" "The set Builtin" "Bash Pattern Matching" "POSIX Shell Command Language" - documentation of all of the POSIX features mentioned in this series. HPR series: Bash Scripting Previous episodes under the heading Bash Tips: HPR episode 1648 "Bash parameter manipulation" HPR episode 1843 "Some Bash tips" HPR episode 1884 "Some more Bash tips" HPR episode 1903 "Some further Bash tips" HPR episode 1951 "Some additional Bash tips" HPR episode 2045 "Some other Bash tips" HPR episode 2278 "Some supplementary Bash tips" HPR episode 2293 "More supplementary Bash tips" HPR episode 2639 "Some ancillary Bash tips - 9" HPR episode 2649 "More ancillary Bash tips - 10" Resources: Examples: bash11_ex1.sh, bash11_ex2.sh, bash11_ex3.sh, bash11_ex4.sh, bash11_ex5.sh…
H
Hacker Public Radio

More ancillary Bash tips - 10 Making decisions in Bash This is my tenth contribution to the Bash Scripting series under the heading of Bash Tips. The previous episodes are listed below in the Links section. We are currently looking at decision making in Bash, and in the last episode we examined the tests themselves. In this episode we’ll look at the constructs that use these tests: looping constructs, conditional constructs and lists of commands. Note: this episode and the preceding one were originally recorded as a single episode, but because it was so long it was split into two. As a consequence the audio contains references to examples such as bash9_ex2.sh where the true name is bash10_ex1.sh. The notes have been updated as necessary but not the audio. Long notes I have provided detailed notes as usual for this episode, and these can be viewed here. Links "GNU BASH Reference Manual" "Bash Looping Constructs" "Bash Conditional Constructs" "Bourne Shell Builtins" HPR series: Bash Scripting Previous episodes under the heading Bash Tips: HPR episode 1648 "Bash parameter manipulation" HPR episode 1843 "Some Bash tips" HPR episode 1884 "Some more Bash tips" HPR episode 1903 "Some further Bash tips" HPR episode 1951 "Some additional Bash tips" HPR episode 2045 "Some other Bash tips" HPR episode 2278 "Some supplementary Bash tips" HPR episode 2293 "More supplementary Bash tips" HPR episode 2639 "Some ancillary Bash tips - 9" Resources: Examples: bash10_ex1.sh, bash10_ex2.sh, bash10_ex3.sh…
H
Hacker Public Radio

Some ancillary Bash tips - 9 Making decisions in Bash This is my ninth contribution to the Bash Scripting series under the heading of Bash Tips. The previous episodes are listed below in the Links section. It seems to me that it would be worthwhile looking at how Bash can be used to make decisions, such as how many times a loop should cycle (looping constructs) or to choose between multiple choices (conditional constructs). Of course we need to look at some of the expressions used in conjunction with the commands that do these tasks – the tests themselves – and we’ll do this in this episode. This is a complex area which I had some trouble with when I first started using Bash, and there is a lot to say about it all. I have prepared a group of HPR shows about this subject, in order to do it justice, and this is the first of the group. Long notes I have provided detailed notes as usual for this episode, and these can be viewed here. Links "GNU BASH Reference Manual" "Bash Conditional Expressions" "Bourne Shell Builtins" HPR series: Bash Scripting Previous episodes under the heading Bash Tips: HPR episode 1648 "Bash parameter manipulation" HPR episode 1843 "Some Bash tips" HPR episode 1884 "Some more Bash tips" HPR episode 1903 "Some further Bash tips" HPR episode 1951 "Some additional Bash tips" HPR episode 2045 "Some other Bash tips" HPR episode 2278 "Some supplementary Bash tips" HPR episode 2293 "More supplementary Bash tips" Resources: Examples: bash9_ex1.sh…
H
Hacker Public Radio

Making a Raspberry Pi inventory Introduction I have a number of Raspberry Pis -- possibly too many -- and I sometimes lose track of which is which, what model, size, name, address each one is. I wanted to be able to keep an inventory of them all, and to this end I wrote myself a little script that can be run on any Pi which will report useful information about it. Every Pi has a unique serial number. Actually it's randomly generated so there may be a few collisions but it's close to unique! It also contains a revision number which encodes various items of information about it such as release date, model, PCB revision and memory. My script decodes this revision number for you based on a published table. I run a Wikimedia instance on a Pi and have used this script to record details of my Pis there as well as what they are being used for and any planned projects. I now feel more organised! Long notes The full-length notes (available here) contain a listing of the script, a brief description of it, and some example output. Links GitLab repository: https://gitlab.com/davmo/what_pi Resources to download: The script what_pi Example output example_output.txt…
H
Hacker Public Radio

Useful Bash functions - part 4 Overview This is the fourth show about the Bash functions I use, and it may be the last unless I come up with something else that I think might be of general interest. There is only one function to look at this time, but it's fairly complex so needs an entire episode devoted to it. As before it would be interesting to receive feedback on this function and would be great if other Bash users contributed ideas of their own. Full Notes Since the notes explaining this subject are long, they have been placed in a file on the server. Links The GNU Bash Reference Manual ANSI-C Quoting section Previous HPR episodes in this group Useful Bash functions: Part 1: 'pad' and 'yes_no' functions Part 2: 'yes_no' revisited Part 3: 'read_value', 'check_value' and 'read_and_check' Download the range_parse function and the range_demo.sh test script.…
H
Hacker Public Radio

A flight itinerary in Bash My daughter flew out to New Zealand before Christmas 2017 to spend some time with her brother, who had been there with his girlfriend since November. I saw her flight itinerary from the airline, but had no idea of how the times related to time back home, so I wrote a little Bash script to calculate times in UTC (my local timezone). Both of my children have travelled a fair bit in the past few years. I like to keep track of where they are and how they are progressing through their journeys because otherwise I tend to worry. This one was a reasonably simple journey, two flights via Doha in Qatar, with not too long a wait between them. The overall journey was long of course. When my daughter flew out to Indonesia in 2015 (4 flights and a boat trip, over 38 hours travel time) I built a spreadsheet. Just whatever provides a good distraction! The rest of the notes, including details of the date command and the script I wrote can be found here. Links GNU documentation for date (You can also use man date or info date for the full details. I prefer the HTML version because I don't like the info tool very much). The GNU Bash Reference Manual Dann Wasko's "Linux in the Shell" episode hpr1182 :: LiTS 023: Date, which is full of useful information. Resources: The script I wrote, called edi_akl (named to denote the starting and ending airports).…
H
Hacker Public Radio

Useful Bash functions - part 3 Overview This is the third show about Bash functions. These are a little more advanced than in the earlier shows, and I thought I'd share them in case they are useful to anyone. As before it would be interesting to receive feedback on these functions and would be great if other Bash users contributed ideas of their own. Full Notes Since the full notes explaining this subject are long, they have been placed in a separate HTML file which can be accessed by clicking this link. Links Previous HPR episodes in this group Useful Bash functions: Part 1: 'pad' and 'yes_no' functions Part 2: 'yes_no' revisited Download the read_value, check_value and read_and_check functions and the trace of read_value.…
H
Hacker Public Radio

Basic bash prompt information Variables and files .bashrc: the RC file where all of this stuff can be set PS1: main prompt variable PS2: continuation prompt PROMPT_COMMAND: a bash function name, run every time prompt is displayed Colors Uses escape sequences There are problems with prompts and escape sequences Multiple escaping String interpretation and variable expansion tput to the rescue! Takes away the need for complex escape codes Must run tput init at the beginning of your .bashrc file TL;DR: Use tput for color strings, add them at the last possible moment, with brackets and backslashes Embedding bash scripts Single quotes are king Will be run every time PS1 is evaluated Otherwise, only run at time of assignment Layout of my prompt Two lines Information/status line Prompt line Status line Starts with current username Changes color when user has mail Next is the hostname (truncated) Separated by an @ symbol, like an email address Changes color when the system is in need of a reboot Checks for /run/reboot_required Current directory Separated from previous items by a pipe Truncated with a tilde if user's home is in the path Prepended with a number indicating the directory stack, if present Appended with the git (±) symbol if we're in a git branch, followed by the name of the branch Prompt line A blue » character Prepended with the number of background processes spawned from this terminal Screenshot: Link to Git Repository https://gitlab.com/windigo-configs/bash.git Editor's Note: added 2017-08-05…
H
Hacker Public Radio

Bash snippet - extglob and scp The Problem Following on from my last show on filename expansion, concentrating on extended patterns and the extglob option, I was asked a question by Jon Kulp in the comment section. Jon was using ls *(*.mp3|*.ogg) to find all OGG and MP3 files in a directory which also held other files. However, when he wanted to copy this subset of files elsewhere he had problems using this expression in an scp command. Having done some investigations to help solve this I thought I'd put what I found into an HPR episode and share it, and this is the show. Along the way clacke commented too and this led me to more investigations! Long notes As often happens, my idea of a brief episode turned into something much longer, so I converted the notes into long notes which you can find here. In them I have marked some sections which you might want to skip over -- unless you are as much of a geek as I am! I have not covered these sections in detail in the audio. Links HPR Show 2293: More supplementary Bash tips StackExchange question: Exclude characters for SCP-filepattern…
H
Hacker Public Radio

Bash snippet - nullglob I recently did an HPR show about Bash filename expansion and described the 'shopt' command and its options. One of the options I talked about was 'nullglob' which controls what is returned from an expansion when no files match. When 'nullglob' is enabled, and a pattern does not match, nothing is returned. When it is disabled (the default) then the pattern itself is returned. Although I didn't think I'd ever need to, I recently wrote a script where I used 'nullglob', and thought I would share a snippet of the code to demonstrate what I did. The script is for managing mail messages containing tag and summary updates. I use Thunderbird for my mail and have configured it to drop these messages into a directory so I can process them. I use Thunderbird's message filters to do this. A certain amount of Spam is also received, and sometimes valid messages need a bit of work before they can be processed. The directory where the messages are saved (the spool area) is stored in the variable 'MAILDROP' earlier in the script. 1 # 2 # Find the files and store their names in an array. Use 'nullglob' so we get 3 # nothing when there is nothing, then revert to the original setting 4 # 5 NG="$(shopt -p nullglob)" 6 shopt -s nullglob 7 MESSAGES=( $MAILDROP/*.eml ) 8 eval "$NG" 9 10 # 11 # Exit if there's nothing to do or report what's there 12 # 13 if [[ ${#MESSAGES[@]} -gt 0 ]]; then 14 echo "Files in the spool area:" 15 printf "%sn" "${MESSAGES[@]}" 16 else 17 echo "The spool area is empty" 18 exit 19 fi The variable 'NG' holds the state of 'nullglob' before the script modifies it. Remember that 'shopt -p' returns a list of commands that will revert the named options to their current state. Next (line 6) the 'nullglob' option is enabled. The array 'MESSAGES' is created on line 7 to hold the list of mail files found in the spool area. This is done with a pattern which matches files that end with the string '.eml'. If we didn't have 'nullglob' enabled then when there were no files the array would contain the pattern - which would be misleading. Having collected the file details 'nullglob' is turned off by executing the command in the variable 'NG' on line 8. You might think that the script could just turn 'nullglob' on then turn it off again when it's no longer needed. However, I prefer to use the technique I have shown here because it needs to have no knowledge of the state of the option before it's set, and restores that state afterwards. By line 13 the array 'MESSAGES' either contains a list of files or is empty. The script checks for these two cases by determining how many elements are in the array. Greater than zero means we have files to process and they are listed in lines 14 and 15. The script then goes on to do various things with the files. If there were no files then the script reports this and exits. That's it! This is not the only way to do this, but I like to write scripts that call as few sub-processes as I can, and this way appeals for that reason. Links HPR show 1648 Bash parameter manipulation looks at variables and arrays in Bash HPR show 2278 Some supplementary Bash tips introduces 'shopt' and 'nullglob…
H
Hacker Public Radio

More supplementary Bash tips Pathname expansion; part 2 of 2 Expansion As we saw in the last episode 2278 (and others in this sub-series) there are eight types of expansion applied to the command line in the following order: Brace expansion (we looked at this subject in episode 1884) Tilde expansion (seen in episode 1903) Parameter and variable expansion (this was covered in episode 1648) Command substitution (seen in episode 1903) Arithmetic expansion (seen in episode 1951) Process substitution (seen in episode 2045) Word splitting (seen in episode 2045) Pathname expansion (the previous episode 2278 and this one) This is the last topic in the (sub-) series about expansion in Bash. In this episode we will look at extended pattern matching as also defined in the “Manual Page Extracts” section at the end of the long notes. Long Show Notes I have written out a moderately long set of notes about this subject and these are available here. Links Previous shows in this series HPR episode 1648 “Bash parameter manipulation” HPR episode 1843 “Some Bash tips” HPR episode 1884 “Some more Bash tips” HPR episode 1903 “Some further Bash tips” HPR episode 1951 “Some additional Bash tips” HPR episode 2045 “Some other Bash tips” HPR episode 2278 “Some supplementary Bash tips” Other HPR series referenced: “Learning sed” series on HPR “Learning Awk” series on HPR Wikipedia article on glob patterns Advanced Bash Scripting Guide: “Globbing” Article on Greg’s Wiki entitled “Globs” Questions about Bash extended globbing on Stack Exchange: Question 1: How to list just one file with ‘ls’ Question 2:…
H
Hacker Public Radio

Some supplementary Bash tips Pathname expansion; part 1 of 2 Expansion As we saw in the last episode 2045 (and others in this sub-series) there are eight types of expansion applied to the command line in the following order: Brace expansion (we looked at this subject in episode 1884) Tilde expansion (seen in episode 1903) Parameter and variable expansion (this was covered in episode 1648) Command substitution (seen in episode 1903) Arithmetic expansion (seen in episode 1951) Process substitution (seen in episode 2045) Word splitting (seen in episode 2045) Pathname expansion (this episode and the next) This is the last topic in the (sub-) series about expansion in Bash. However, when writing the notes for this episode it became apparent that there was too much to fit into a single HPR episode. Consequently I have made it into two. In this episode we will look at simple pathname expansion and some of the ways in which its behaviour can be controlled. In the next episode we’ll finish by looking at extended pattern matching. Both are included in the “Manual Page Extracts” section at the end of the long notes. Long Show Notes I have written out a moderately long set of notes about this subject and these are available here. Links Previous shows in this series HPR episode 1648 “Bash parameter manipulation” (2014-11-26) HPR episode 1843 “Some Bash tips” (2015-08-26) HPR episode 1884 “Some more Bash tips” (2015-10-22) HPR episode 1903 “Some further Bash tips” (2015-11-18) HPR episode 1951 “Some additional Bash tips” (2016-01-25) HPR episode 2045 “Some other Bash tips” (2016-06-03) Other HPR series referenced: “Learning sed” series on HPR “Learning Awk” series on HPR Wikipedia article on glob patterns Advanced Bash Scripting Guide: “Globbing” Article on Greg’s Wiki entitled “Globs”…
H
Hacker Public Radio

Audio speedup script Back in 2015 Ken Fallon did a show (episode 1766) on how to use sox to truncate silence and speed up audio. Inspired by this I wrote a Bash script to aid my use of the technique, which I thought I’d share with you. I have written out detailed notes for this episode describing the script and examining how it works. Click the link to see them. Links HPR show 1766 “The Sox of Silence”: https://hackerpublicradio.org/eps/hpr1766/ Original article on doing clever things with sox: https://digitalcardboard.com/blog/2009/08/25/the-sox-of-silence/ The speedup script for download: https://hackerpublicradio.org/eps/hpr2135/hpr2135/speedup The repository containing the speedup script on GitLab: https://gitlab.com/davmo/hprmisc…
ברוכים הבאים אל Player FM!
Player FM סורק את האינטרנט עבור פודקאסטים באיכות גבוהה בשבילכם כדי שתהנו מהם כרגע. זה יישום הפודקאסט הטוב ביותר והוא עובד על אנדרואיד, iPhone ואינטרנט. הירשמו לסנכרון מנויים במכשירים שונים.