Skip to content
Artwork for Hacker Public Radio
TechnologyTech NewsEducationExplicit

Hacker Public Radio

Hacker Public Radio

Hacker Public Radio is an podcast that releases shows every weekday Monday through Friday. Our shows are produced by the community (you) and can be on any topic that are of interest to hackers and hobbyists.

Play
  • 21 episodes
  • English
Counted on this page — what you have heard stays on this device, so it is not something the list can be paged by.
  • Friday · length unknown

    HPR4715: friedcamp interviews part 2: Thomas Farstrike

    This show has been flagged as Clean by the host. MicroPythonOS https://MicroPythonOS.org/ https://github.com/MicroPythonOS/MicroPythonOS Thomas Farstrike https://github.com/ThomasFarstrike Provide feedback on this episode.

  • Thursday · length unknown

    HPR4714: HPR Beer Garden 18 - Amber Ale

    This show has been flagged as Clean by the host. The HPR Beer Garden returns for it's eighteenth episode with a look at Amber ales. Dave tries out Hobgoblin Amber , whilst Kevie samples Banks's Amber . Connect with the guys on Untappd : Dave Kevie The intro sounds for the show are used from: https://freesound.org/people/mixtus/sounds/329806/ https://freesound.org/people/j1987/sounds/123003/ https://freesound.org/people/greatsoundstube/sounds/628437/ The next three beer styles to be reviewed are: lager mild bitter Provide feedback on this episode.

  • Wednesday · length unknown

    HPR4713: July2026 Community News response, and Future Plans

    This show has been flagged as Explicit by the host. The show I'm responding to https://hackerpublicradio.org/eps/hpr4696/index.html The Album I plan on reviewing in the future (not the best album to start with getting into noise, but it's one of the more famous ones) https://open.spotify.com/album/2T2a5nzJ0uHJVhLkgiMeYA Reading on why I will never review anything by Boyd Rice (also if you don't mind paying for a patreon, the podcast The Empire Never Ended did a patreon exclusive episode on Boyd Rice and his ties to Neo-Nazi and Neo-Fascist groups) https://spencersunshine.com/2024/05/21/boyd-rice-neo-nazi-collaborator-video/ Provide feedback on this episode.

  • Tuesday · length unknown

    HPR4712: friedcamp interviews part 1: Wim van Gool

    This show has been flagged as Clean by the host. Fri3d Camp is a biennial family-friendly summer camp for hackers, creators and do-it-yourselfers. https://fri3d.be/wat/ campbadge at fri3dcamp 2026: https://fri3d.be/en/badge/ Hardware design: Wim van Gool: https://mastodon.social/@wimvangool Contact: badge@fri3d.be Software design: MicroPythonOS Thomas Farstrike Provide feedback on this episode.

  • August 24 · length unknown

    HPR4711: Second-Hand Phone

    This show has been flagged as Clean by the host. I have a second phone. I use it for my family, close friends, and my sanity to keep my smart phone at bay. It is inexpensive and can be extremely useful. In this podcast, I discuss "Why," "Benefits," "Drawbacks," and "Rules" that I have in place. If you are looking for a way to get away from the daily rigors of smartphone use, this may be your episode. Provide feedback on this episode.

  • August 21 · length unknown

    HPR4710: Civilization VI

    This show has been flagged as Clean by the host. Civilization VI, released in 2016, was a further evolution of the franchise that added interesting new features. We introduce it in this episode. Civilization VI Released in 2016, Civ VI is probably still the most played version of the game. Although there has been a general gap of 5-6 years between versions, the effects of the Covid-19 pandemic slowed down many things. Since early 2025 we have had Civilization VII come out, but in my opinion it is still being tweaked and refined. In the meantime, Civilization VI is the game I play now when I play Civ. I’ve played all of them from the first, and put in many hours here. Since I now play Civ on Steam mostly, I have statistics! I played Civ V for a total of 769 hours, and so far I have played Civ VI for 689 hours, but since this is what I play for now I will probably exceed my Civ V hours pretty soon. BTW, I probably have well over 1000 hours on Civ II, which I think I have played the most, and certainly more than 3000 hours total over all all versions. I’m going to cover this without worrying too much about whether it is the base game or an expansion. Fact is, Firaxis have started moving to something more akin to a subscription model when they introduced the New Frontier Pass, which works very well when you are on Steam. The idea was that you bought this pass, and very few months got new content, and on Steam it would automatically be downloaded to your account. That is not to say that there weren’t actual expansions, but since the last thing they released was this “pass”, i’m kind of wondering what they will do with Civ VII. In any case, let’s take a look at this. Gameplay Again, you start with a tribe in 4000BC which founds your first city, and you immediately begin building units, exploring, researching, and developing your city. this is a time-tested mechanic that never changes. but there are some interesting changes that make this game fascinating. First, in the earlier versions of Civ you thought of yourself as playing a particular civ, which came with a particular leader. In different versions of Civ the name of the leader might change, like for France you might have Napoleon on some versions, or Joan of Arc in another, but in each case one civ gets one leader, so you tended to think of yourself as playing the nation. Rome might be Caesar in one version, Augustus in another, or Trajan in yet another. (Fun fact: Sid Meier says he always plays as Rome because it just feels right to him). In Civ VI this linkage is broken. One leader, Eleanor of Aquitaine, can be played as the Queen of England, or she can be played as the Queen of France. And each version has different abilities and strengths. If you want a fairly easy Culture victory, play her as Queen of France, and watch as other players’ cities rebel and join your Empire because they admire you so much. Teddy Roosevelt also has two different manifestations, Rough Rider Teddy, and Big Stick Teddy, when you have all the expansions. China has two possible leaders, with different strengths: Qin Shi Huang, and Kublai Khan. And Kublai Khan can be either Chinese or Mongolian, with different strengths. So in Civ VI you don’t think of what Civ you want to play, you think of which leader you want to play. Every leader comes with a Civilization Ability, a Unique Unit, and a Unique Infrastructure. These matter a lot. For example, take John Curtin, the leader of the Australian civilization. His Civilization Ability is called Land Down Under, and it gives him +3 Housing in coastalcities. Building a Pasture triggers a Culture Bomb, claiming surrounding tiles. Campus, Commercial Hub, Holy Site, and Theater Squaredistricts gain +1 to their yields in tiles with Charming Appeal, and +3 in tiles with Breathtaking Appeal. Then his Unique Unit is the Digger, a melee military unit that replaces the Infantry unit. And his Unique Infrastructure is tile improvement called the Outback Station. This gives you increased food, production, and housing, some of which varies according to what is on surrounding tiles. The point is that each leader gives you very specific advantages that you should play to. In Civ VI it is even more important to tailor your strategy to the particular leader. Leaders like Frederic Barbarossa or Simon Bolivar are very good for Domination, while Peter the Great and Saladin are very good for Religious victories. If you take a random leader be ready to adapt your play style and strategy to fit, or alternatively decide what kind of victory you want to achieve and pick a leader who is good at it. Or if you want a real challenge, pick a leader who is not suited to the victory condition you are aiming at. But keep in mind that the game may take you in places you didn’t expect. One game I picked Wilfrid Laurier of Canada, who is ideal for Diplomatic and Cultural victories, and I thought I would be going for a Cultural victory. But Wilfrid’s strengths come from his advantages on Tundra land tiles, and I somehow managed to spawn in the middle of the map with no Tundra tiles at all in my empire. I had work hard to manage a Science victory in that case. Districts This is a major change in Civ. In earlier versions you built buildings inside of cities, and you tended to build the same buildings in most or all cities. You were only limited by your ability to generate Production to get them done. Civ VI is different. You have to place Districts on specific tiles, and and you can then develop the district with added buildings. If you want to develop your industry, you can place an Industrial Zone, and then add a Workshop, then a Factory, then a Power plant, and so on, each one increasing your Production. For Science you place down a Campus District, then a Library, then a University, then a Research Lab. And the game mechanic means you cannot built everything in every city. You can place one district at the start, then one more when your city reaches a population of 4, then a third one when you reach 7, and so on with each added population of three allowing one more district. The point is to force you to make choices. Districts get adjacency bonuses which increase their output. The Campus (generates Science) and the Holy Site (generates Faith) both benefit from adjacent Mountains, and the effect is additive. So if you find a tile with three mountains around it, you will want to place one of these districts there. Districts also get adjacency bonuses from other districts, so the planning the layout of your cities is really important to maximize these bonuses. And they can get bonuses even with adjacent Districts that belong to a different city! Another key district is the Encampment, which let you build better, more veteran military units. Since building units requires Production, you should build build an Encampment in a city which has a lot of Production, and that probably means one with an Industrial Zone. A Harbor District would go in a city with coastal tiles, of course. All of this requires planning. Expert players will usually start out by exploring to see what the map looks like around them, what terrain features they have to work with, what resources are available, and so on. Then, around turn ten they will plan out their next cities, and figure out where they want to place districts and so on. There is a built-in “map pin” system for this, and it can be improved by installing the right mod. While you don’t have to do this, it does help you to be successful. Maps and Terrain Terrain features matter a lot in this game. We already mentioned adjacency bonuses of Mountains for Holy Sites and Campuses, but there is much more. The map is divided into Continents, and it is quite normal for a contiguous land mass to contain two or more continents if it is large enough. Think of how Europe and Asia are really just one large land mass to see what I mean. This matters because certain units may defend differently depending on which continent they are on, or some civilizations may be affected from having cities on a different continent. Terrain features like Rivers are extremely important for the placement of cities because they provide fresh water. You can sometimes get around that by building an Aqueduct to bring water from a Lake or a Mountain, but that means using up one of your city tiles, and spending production to build it. If you can place your city on a river you can avoid that problem and get off to a fast start. But the downside is that rivers can flood, and that can wreck your improvements. A big idea for terrain is Appeal. Each tile has an Appeal level ranging from Disgusting to Breathtaking, and it is determined by a combination of the tile’s features themselves and by adjacencies. The modifiers are added together to determine the Appeal level of the tile, and there is a lens you use to view your Appeal levels on all tiles, which are color coded. This matters particularly if you are trying for a Culture victory. Culture victories are own by generating Tourism, and while some that can come from things like Museums and Wonders, you will really want to maximize your Tourism to win this game, and two good ways to do that are building National Parks and Seaside Resorts. You can only do that if the appeal is at least Charming (or even better, Breathtaking). If you find you cannot build them in what seems like a good spot, chances are Appeal is the problem. So check that out. You can, for instance, remove marshes (which give negative appeal), and plant forests (which add appeal), and that might be all it takes to get these going. The underlying issue in managing your cities is that you only have so many tiles, and a tile that might be great for a farm might also be great for a District. You need food to grow, and you need to grow to put down Districts, so you are always making choices about this, and that is what makes this a great strategy game. Other Resources Civilization 6 Tutorial: In Game Settings Links https://www.pcgamesn.com/civilization-vii/narrative-lead-job-posting https://civilization.fandom.com/wiki/Qin_Shi_Huang_(Civ6) https://civilization.fandom.com/wiki/Kublai_Khan_(Chinese)_(Civ6) https://civilization.fandom.com/wiki/Housing_(Civ6) https://civilization.fandom.com/wiki/Coastal_(Civ6) https://civilization.fandom.com/wiki/Pasture_(Civ6) https://civilization.fandom.com/wiki/Tile_(Civ6) https://civilization.fandom.com/wiki/Campus_(Civ6) https://civilization.fandom.com/wiki/Commercial_Hub_(Civ6) https://civilization.fandom.com/wiki/Holy_Site_(Civ6) https://civilization.fandom.com/wiki/Theater_Square_(Civ6) https://civilization.fandom.com/wiki/District_(Civ6) https://civilization.fandom.com/wiki/Appeal_(Civ6) https://civilization.fandom.com/wiki/Continent_(Civ6) https://www.youtube.com/watch?v=lkas_uiq_fk https://www.palain.com/gaming/civilization-vi/ Provide feedback on this episode.

  • August 20 · length unknown

    HPR4709: Peertube: my two penneth

    This show has been flagged as Clean by the host. Kevie gives a brief talk about PeerTube and also some of the issues that he has experienced, especially with the Android apps, and shares his subscriptions: More Fun Making It Main Oldschooleducation channel The Linux Experiment Nick's Workshop Arthurpizza Josh's Junk Drawer Reece's Rambles Gardner Brynat Veronica Explains Andy Piper Provide feedback on this episode.

  • August 19 · length unknown

    HPR4708: Programmable Logic Controls - Episode 1

    This show has been flagged as Clean by the host. Introduction 01 This is the first episode in an 8 part series. 02 This series is on programmable logic controllers, or PLCs as they are commonly known. What is a PLC you ask? In short, it is a general purpose programmable industrial control device. They are used all through industry in factories, utilities, and anywhere industrial machines need to be controlled. 03 They are a fully integrated system of hardware, software, and development environment tailored specifically for automatic industrial equipment. It is probably easiest to describe them by first giving a bit of historical background as to what preceded them. 04 The Early Days of Automation You have probably heard of the Jacquard loom of the early 19th century and its use of punch cards with respect to it being one of the technologies which eventually lead to computing. However, for our purposes here, its significance is that it was an early form of industrial automation control system, since it was after all controlling a machine in a factory. 05 For other types of machines, a common purely mechanical means of having the various parts of a complex machine move in a coordinated manner was through the use of shafts and cams. A series of cams located on a shaft or set of shafts connected by gears, could move parts of a machine, turn valves on or off, and generally coordinate the parts of a machine. With the spread of the use of electricity in factories in the early 20th century, it was now possible to use the new electrical technology to perform control and automation functions. 06 The Background of Relay Logic I will need to explain some electromechanical terminology here as it is necessary to understand these terms and the concepts behind them in order to understand PLCs, as the latter is an evolution of its predecessors and uses the same terms. What preceded PLCs was what was commonly known as "relay logic". 07 What is a Relay A relay is an electromechanical device that responds to and controls the flow of electric current. A relay has a "coil" which as the name implies is a coil of conductive wire. When you energize the coil, that is you apply electric current to it, it forms an electromagnet. 08 This electromagnet draws in an armature. The armature is a moving piece of metal which is attracted to the coil when the latter is energized. The relay being activated is referred to as closing. Deactivating is referred to as opening. Alternative names for these states are "pulls in" and "drops out" respectively. 09 The armature in turn is attached to one or more contacts. You can think of a contact as being like a switch. When the switch is turned one way, the electrical path is closed and current can flow. When it is turned the other way, the electrical path is broken and current flow is interrupted. 10 Contacts can be normally open, in which case the path is closed and current can flow when the relay turns on. Alternatively, they can be normally closed, in which case the path is closed and current can flow when the relay turns off. A relay can, and typically does, have multiple contacts, including both normally open and normally closed. Remember these terms, coil, contact, normally open, and normally closed. 11 What is a Latching Relay There is a special type of relay known as a latching relay. This was only occasionally used in relay control circuits, but the concepts behind it will become more important when we talk about actual PLCs. A latching relay has two coils. One coil is used to turn on or "set" the relay. The other coil is used to turn off or "reset" the relay. 12 The relay has either a mechanical latching mechanism or a magnet which is used to hold the relay in the set (or in other words, closed) position even if the set coil is de-energized. You must energize the reset coil in order to reset or "open" the relay. A latching relay provides the equivalent of one "bit" of memory which retains its last state even if the power to the machine is turned off. 13 Latching relays were used in applications where it was important that the relay logic circuit remember its last state. While not frequently used in relay control circuits due to their greater cost and complexity, the concept was to be more extensively used in PLC programs when set and reset instructions were provided which performed the equivalent function in software where there were no similar cost considerations to worry about. 14 Thus set and reset were to be much more frequently used in PLC programs than they were when they were actual relays. Add these terms to your list of things to remember - latch, unlatch, set and reset. 15 What is a Contactor I will mention another term now in case it happens to come up later. This is "contactor". A contactor is basically just a large relay. It is typically used to control large electrical loads such as motors and heaters. 16 Smaller relays are typically just called "relays", or sometimes "control relays". These be used to create either logic circuits or control smaller electrical loads such as lights or pneumatic or hydraulic valves. This may seem like a lot of jargon, but bear with me, I will make analogies to computers when appropriate. 17 Input and Output Devices If you want to do some useful work, you will need some I/O. Typical input devices include the following. 18 Push buttons. These are buttons which are pressed by the operator to command the machine to do something. 19 Selector switches. These are switches which are typically rotated to turn on or off and maintain their position. These can have multiple positions, each of which can activate a separate input. 20 Pilot lights. These are lights which are used to provide feedback to the operator. 21 Limit switches. These are mechanical switches which parts of the machine activate, rather than the operator activating them. This can be used to determine what position the various parts of the machine are in at any given time. 22 Proximity sensors. These are essentially solid state limit switches which are more reliable than mechanical switches as they are less subject to wear and tear. These are often colloquially abbreviated as "proxies". 23 Solenoid valves. These are like relays in that an electromagnetic coil is activated. However, instead of activating another electrical contact, it activates a pneumatic or hydraulic valve. This valve in turn typically allows air or hydraulic fluid to move a piston within a cylinder, which then moves some mechanical part of the machine. A typical machine will have lots and lots of proximity sensors and solenoid valves. 24 Relay Logic All of these inputs and outputs require some sort of logic to coordinate them. This is where control relays came in. 25 If having the output of one electrical device being able to control another electrical device sounds a bit like a transistor, then yes relays are analogous to electronic transistors. However, while transistors are a mid 20th century invention, relays date from the mid 19th century. 26 Like with transistors, it is possible to encode logic into a network of wires connecting relays together, along with inputs from switches and other input devices. By wiring sensors and relays together in the right order, it is possible to create reasonably complex sequences of operation to control a machine in an automatic manner. 27 Relay Boolean Logic Wiring relay contacts in series creates "and" conditions. Wiring them in parallel creates "or" conditions. Using normally closed relay contacts creates "not" conditions. By feeding a relay's own contacts back into the circuit leading up to its coil, it is possible to have a relay remember its own state. Each relay therefore could be thought of as one bit of logic in a boolean logic circuit. 28 Timers and Counters Special timing relays could be used to create a time delay between the relay energizing or de-energizing, and the contacts closing or opening. A timing relay which imposed a delay after being energized is an "on delay timer". A timing relay which imposed a delay after being de-energized is an "off delay timer". 29 Timing relays were often pneumatic. They had a small rubber bellows that leaked air slowly through a adjustable orifice. The bellows would prevent the relay from opening or closing, depending on the type, until enough air had leaked out for it to close or open. For more accuracy or for longer time delays, motor driven clock timers could be used. 30 Special counter relays could be used to require an input to turn on or off a specified number of times before activating the relay outputs. Counters typically used a ratchet mechanism to count up to a preset before activating. 31 Later timing and counting relays used electronic timers and counters, but these arrived relatively late at a time when relay logic was on its way out. 32 Electrical Panels Large numbers of relays would be mounted on panels in large electrical enclosures, with the wires running between them, and also out to the limit switches, valves, and other devices mounted on the machine. 33 Designing the Logic Circuit The logic or program would be encoded in the selection of the devices and in the wires running between them. To design and document this logic, the designer would create electrical drawings. These drawings would follow one of two different styles. 34 In one style, the two power wires, either hot and neutral in the case of AC power, or positive and negative in the case of DC power, were drawn as vertical lines down each side of the page of the drawing. These vertical lines are known as the "rails". Wires would then be drawn horizontally across the page from left to right showing the connections between push buttons, switches, and relay contacts across to the relay coils or pilot lights on the right. 35 The physical connections between relay coils and relay contacts were not normally shown on the drawings, although they may in the case of push buttons or selector switches with multiple contacts. Instead you would rely on the labels or names to see which contacts were associated with which relay coils, limits switches, or push buttons. 36 There are standard naming conventions for devices which I won't go into here. However, this means that the relay coils could be on one page of the drawing set, and the contacts could be anywhere else in the drawing set. It was convention to write a cross reference beside the relay coil to list where its contacts are used in the drawing. 37 Ladder Rungs In practical terms, what this meant is that the logic drawing tended to take the form of many independent horizontal sets of wiring and contacts looking rather like the rungs of a ladder. Thus these drawings came to be known as "ladder diagrams" or "ladder drawings". The horizontal elements were known as "rungs". 38 Standard Symbols Each type of device had a standard symbol so you could see at a glance what it was. For example a relay coil was a circle. A normally open relay contact was two short vertical lines separating a break in the wire circuit. A normally closed relay contact was just a normally open contact with a diagonal line drawn across it. 39 Logic Flow By convention, drawings were read from top to bottom, left to right. In actual practice operations could happen in parallel and you had to be careful to avoid introducing what was called a "relay race" where the outcome of an operation depended upon which of two parallel operations completed first. A relay race could produce unpredictable results depending upon which of the operations completed first and therefore must be avoided. 40 Engineers, technicians, and electricians were expected to become proficient in reading and understanding these ladder diagrams in order to design and troubleshoot equipment. To someone who was experienced in the field, reading and understanding these diagrams became second nature. 41 DIN Drawings I mentioned there were two styles of drawings. The other style is known as DIN, which stands for Deutsches Institut fur Normung, or German Standards Institute in English. This is basically just a ladder diagram turned on its side, with the rails running horizontally from left to right, and the rungs running vertically from top to bottom. I have mentioned DIN drawings here for completeness, but even those countries which still use DIN style drawings for documenting wiring use vertical ladders when ladder logic went electronic. 42 Comparison to Electronic Logic Gates If you are familiar with electronic and, or, nand, and nor gates some of the above concepts should familiar to you. Some of the concepts are indeed analogous. However these electromechanical conventions predate the existence of solid state. 43 The drawings also follow completely different principles. Whereas solid state logic gate drawings show inputs and outputs on a single device grouped together in a single block with complex interconnections, electrical ladder drawings separate them, which has a number of very significant consequences. 44 First it greatly simplifies drawing the interconnections. Second, it allows inputs and outputs to be grouped together by function rather than by physical packaging. Thirdly it allows drawings to be spread over many smaller standard size sheets which in turn allows a functional collection of related rungs to be viewed in a single glance. These three factors were to be of great significance when physical relays were replaced by software. -------------------- 45 Historical Origins and Development Origins Nobody seems to know when or where industrial relay logic was first introduced. Best guesses seem to say some time after the widespread electrification of factories in the early 20th century. Automation in the era of steam power seemed to rely mainly on the profile of mechanical cams mounted on shafts to time machine operations. Most sources seem pretty confident that relay logic was widespread by the 1940s or 50s. 46 Solid State The introduction of transistors did not immediately displace relays for control purposes. Relays had the ability to handle significant amounts of power directly, allowing them to interface with inputs and outputs directly. Transistors would have still required interposing relays anyway, increasing the component count and complicating the system for little benefit. 47 There were solid state logic modules developed specifically to replace relays in control logic, but these were not widely used. These solid state logic modules still required wiring connections between them, limiting their advantages over electromechanical relays. A number of families of electromechanical control relays were developed by a number of companies, and these tended to be very robust and reliable, although rather expensive. 48 Conclusion In this episode I have covered the following. What is a relay. Common input and output devices. How relays are used to create boolean logic systems. Designing relay logic systems and the electrical drawings used to document them. The brief history of relay logic systems. 49 Terms to Remember Here are some terms you may wish to remember. Programmable Logic Controller, also known as "PLC" Control relay Coils Contacts Normally open Normally closed 50 Latch Unlatch Set Reset 51 On delay timers Off delay timers Counters Push buttons Pilot lights Limit switches Proximity switches, also known as "proxies" Ladder diagrams Ladder rails Ladder rungs 52 Next Episode In the next episode I will discuss the following The origins of PLCs. How they evolved from relay logic. How and why physical relays and wiring became virtual relays in software. 53 Did you think that visual or graphical programming was something new? Listen to the next episode and find out that people were doing it in factories half a century ago back when you were still trying to get your first Fortran program to run on a mainframe. 54 This has been the first episode in an 8 part series. -------------------- Provide feedback on this episode.

  • August 18 · length unknown

    HPR4707: UNIX Curio #12 - expr

    This show has been flagged as Clean by the host. This series is dedicated to exploring little-known—and occasionally useful—trinkets lurking in the dusty corners of UNIX-like operating systems. Arithmetic is something that one would normally expect computers to be able to do. With UNIX, one could of course always write a program to perform a calculation, but for people like me who are bad at programming, it would be nice to have a tool that makes things a bit easier. First Edition UNIX in 1971 included such a tool, called dc , which stands for "desk calculator" 1 . This utility performed integer arithmetic (though later versions can handle real numbers) using reverse Polish notation. To divide 11 by 4 with this method, instead of entering "11 ÷ 4 =", you would key in "11 ENTER 4 ENTER ÷". The very first calculator I ever used, one made by Hewlett-Packard that my father brought home from work a few times, employed reverse Polish notation but I have never gotten used to it. All the calculators I have made significant use of and bought for myself used the more common infix notation "11 ÷ 4"—I also prefer computer utilities following that pattern, so I almost never use dc . For reasons explained in the rationale for the bc utility 2 , dc has not been standardized in POSIX despite its long tenure. However, while it doesn't seem to get a lot of attention, I still would not consider dc to be a UNIX Curio. Today, it is possible to do integer arithmetic in a standard POSIX shell without any outside utilities. This is called "arithmetic expansion" and is described in references or manual pages for many shells. It wasn't always this way, however. Before a shell was available that supported arithmetic expansion, you needed to call another utility for your calculations, and expr was one of those 3 . That program is the UNIX Curio for this episode. Some people might pronounce this name, but I find it awkward to say, so I just spell out expr the same as I would do with dc . Its name is an abbreviation of "expression", and it takes arguments representing an expression. An expression is formed by combining integers or strings with zero or more operator symbols. There is quite a variety of operators—some are mathematical, some perform comparisons, one matches a regular expression, and others are used for grouping or logical tests. Since we started this episode talking about arithmetic, let's tackle those first. The "+", "-", "*", and "/" symbols are for performing addition, subtraction, multiplication, and division respectively, as is common in many programming and scripting languages. The "%" produces the remainder of integer division. So, expr 11 / 4 would output 2 ; it only does integer calculations. The command expr 11 % 4 would output 3 —in this case, the remainder left after "4" is removed from "11" twice. Take note that expr expects the integers or strings and operators it is given to all be separate arguments. Running expr 11/4 would just output the string 11/4 because the slash is not treated as being an operator. You also need to be careful with characters that have meaning to the shell— expr 11 * 4 would probably result in an error because the shell will expand the asterisk to a list of files in the current directory. You would have to use expr 11 \* 4 or expr 11 "*" 4 instead to multiply those numbers. It is possible for each integer to be preceded by a hyphen (with no spaces in between), meaning the number is negative. However, you need to be careful here, too. The command expr $a + 1 could potentially fail if the value of $a is -1 —some implementations might treat the -1 as being an option to expr . (While POSIX does not specify any options, an implementation of the utility could add them as an extension.) The safer method is to make sure the variable doesn't appear first: expr 1 + $a would work, as would expr \( $a \) + 1 . Parentheses can be used for grouping; in this example, they just prevent the value of $a from being the first argument. Another way to prevent a value from being treated as an option is to put the standard two hyphens after expr , signaling the end of options (for example, expr -- $a + 1 ). The result of evaluating the expression is printed to standard output. The exit status of expr is also set based on the result—if the expression is evaluated successfully and the result is not zero or the null string, the exit status will be 0. The exit status is 1 if evaluation is successful and results in either zero or the null string. When the expression is invalid, the exit status will be 2 and if some other error occurs, it will be greater than 2. A script using expr can therefore potentially take some action depending on its exit status, the value it outputs, or both. The next set of operators recognized by expr consists of comparison operators. These include "=", "!=", ">", ">=", "<", and "<=", and they work just how you would expect with integers. If one or both of the arguments are strings, however, instead of doing a numerical comparison, the arguments are compared using the collation sequence in the current locale. When the comparison is true, expr outputs "1" and returns an exit status of 0; if false, it outputs "0" and returns a status of 1. It is important to be careful in the arguments you use; 10 = 10.0 would evaluate to false because the period forces a string comparison rather than a numerical one. By contrast, 10 = 010 would evaluate to true; unlike some other utilities, expr does not consider a leading zero to mean an octal number. All numbers are treated as decimal and standard expr has no method for working with other bases. There are also logical operators, though they might not act exactly the way you would expect if you are used to other programming languages. When a & symbol appears between two expressions, it outputs the result of the first one if both expressions evaluate to something that is not 0 or a null string. Otherwise, it outputs 0. If a | symbol appears between two expressions, it outputs the result of the first one provided it evaluates to something that is not 0 or a null string. Otherwise, it outputs the evaluation of the second expression if that is not a null string. If neither of these are true, it outputs 0. As with some other operators, these are significant to the shell so they need to be quoted. I mentioned parentheses before; these can be used for grouping. The last operator I will cover is : and it is quite different from the others. Instead of performing a mathematical or logical function, it instead performs a regular expression match. The expression before the colon is treated as the string to match against, and the expression after the colon is a basic regular expression. (Be careful, features of extended regular expressions are not available.) There is one special characteristic to the match—it must occur starting at the beginning of the string, as if ^ appeared at the beginning of the regular expression. The colon operator normally returns the number of characters matched by the regular expression. So, for example, expr "x$a" : ".*" - 1 would return the length of the string in $a . (The "x" is used in case $a happens to be a null string. Also, ${#a} is a more efficient way to return the length of $a within modern shells.) However, if the regular expression contains any subexpressions , indicated by \( subexpression \) , this operator instead returns what is matched by the first subexpression, or a null string if that does not match. So in some cases, expr could be used in place of another tool like grep , sed , or awk . There is one final case: where an integer or string appears without any operators at all. In that situation, it is simply output as a string with no calculations, comparisons, or matching performed. It's as if you used echo with a single argument. So why would you want to use expr ? For mathematical calculations, arithmetic expansion will certainly be faster because it happens within the shell. While expr does give you an exit status, allowing it to be used within shell constructs like if and while , it is likely that combining arithmetic expansion with the test utility (which is built in to many shells) would use fewer resources. However, arithmetic expansion has limits: POSIX only requires it to operate on signed long integers; what this means in practice depends on the platform you are running on. In contrast, the standard for expr does not say anything about what range of integers must be supported. GNU's version uses arbitrary precision 4 , allowing it to represent very huge integers like bc does. The implementations of expr included with FreeBSD 15.0, NetBSD 10.1, and OpenIndiana 2025.10 all use a 64-bit signed representation (at least on the virtual machine I tested). While on FreeBSD and NetBSD an error results when the limit it can faithfully represent is exceeded, the OpenIndiana version just overflows and returns an incorrect value. So one cannot depend on expr providing any extra capabilities than shell arithmetic expansion unless the exact implementation is known. If expr can't be relied on for any improvements in arithmetic relative to other tools, what about comparisons? For numerical comparisons, test offers the same set of options that expr does. When it comes to strings, the POSIX standard only added < and > operators to the test utility in 2024 5 — earlier versions just offered = and != 6 , so expr guaranteed more functionality up until just recently. There is a semantic difference between how = and != in the two utilities behave with strings. In test , those operators mean "is (or is not) identical", while in expr they mean "collates (or does not collate) the same in the current locale". If this is important to you, there is no way to get the other behavior under standard POSIX with either of these utilities, so you have to choose the right one. I have to say that it is unclear to me how "collates the same" is applied in practice; some examples I tried did not reflect what I expected. My reading of the Unicode standards would imply that the presence of a ZERO WIDTH SPACE character (Unicode code point U+200B, represented in octal escape sequences as \342\200\213) does not affect how a string collates. However, expr seems not to ignore it. The below was obtained on Debian 12 using the en_US.UTF-8 (US English) locale, but I got the same results on FreeBSD 15.0. Reminder: in the output of expr , 1 means true and 0 means false. $ printf 'abcd\n' abcd $ printf 'ab\342\200\213cd\n' ab​cd $ expr "abcd" = "$(printf 'ab\342\200\213cd')" 0 $ expr "abcd" \> "$(printf 'ab\342\200\213cd')" 1 Another section of the same Unicode reference outright states that the three code points U+212B, U+00C5, and A followed by U+030A are equivalent. I tried the below on Debian 12, using the da_DK.UTF-8 (Danish) locale to be sure this character was not excluded. These were not treated as being the same by expr . All three had a different appearance in the terminal program I was using (Konsole). $ printf '\342\204\253\n' Å $ printf '\303\205\n' Å $ printf 'A\314\212\n' Å $ expr "$(printf '\342\204\253')" = "$(printf '\303\205')" 0 $ expr "$(printf '\342\204\253')" \< "$(printf '\303\205')" 1 $ expr "$(printf '\303\205')" = "$(printf 'A\314\212')" 0 $ expr "$(printf '\303\205')" \> "$(printf 'A\314\212')" 1 $ expr "$(printf '\342\204\253')" = "$(printf 'A\314\212')" 0 $ expr "$(printf '\342\204\253')" \> "$(printf 'A\314\212')" 1 Another difference is that test has two separate sets of comparison operators—one set does numerical comparisons and the other does string comparisons. Normally in a script, you would want to be as explicit as possible about the type of comparison you want. However, there might be circumstances where you want the type of comparison to depend on what the two values are. That is how expr works, so in that situation you might want to use it instead. It would be possible to use a case construct in the shell to choose, based on the values, whether to use the arithmetic or string comparison operators with test , but expr does that for you automatically (see the Appendix for an example of duplicating its behavior). For matching using the : operator, expr offers a syntax that is slightly less flexible than grep . On some systems, expr can be a smaller binary, but at most I've seen it be about 80 kilobytes smaller, so that's unlikely to be a real savings in practice. To get the length of a regular expression match, one could use the match() function of awk instead. The ability of expr to return a subexpression match is neat, but sed can also accomplish that. The expr utility first appeared 7 in a version of UNIX from Bell Laboratories called the Programmer's Workbench 8 1.0, released in 1977. From there, it made its way into 1979's Seventh Edition UNIX 9 , which is where the test utility made its first appearance 10 . The overlap between the capabilities of the two utilities seems a little strange to me, but I haven't dug into details of the history—perhaps they were developed separately and just happened to meet in Seventh Edition. It took substantially longer for arithmetic to be a feature built directly into the shell, at least on versions of UNIX from Bell Laboratories/AT&T. The Korn shell (ksh), included with Eighth Edition UNIX 11 in 1985, offered it with the let keyword or (( ... )) syntax, but these have not been adopted by POSIX. I couldn't track down exactly when the standard shell gained the syntax $(( ... )) for arithmetic expansion used today—it was not present in 1989's Tenth Edition UNIX 12 , but did appear in The Open Group's CAE Specification from 1994 13 (a standard that existed alongside POSIX), so presumably it showed up somewhere in between. Separately, BSD's C shell (csh) included arithmetic expressions from its first appearance in 2BSD 14 in 1979, very much in line with that shell adopting syntax from the C programming language, so the concept was not new. My overall conclusion is that almost everything that expr does can be performed with another, better-known utility. The exception would be the way the = and != operators behave, which to my knowledge isn't duplicated by another standard program. In some cases, using a different utility would require a bit more complex work, so if your script didn't already call that utility, you might be better off with expr instead. I am unlikely to start making much use of it, but still enjoy the fact that I learned a bit more about it. This episode focuses on integer arithmetic because that is what expr is capable of doing. More details of arithmetic expansion within the shell are covered in Hacker Public Radio episode 1951 . If you are instead looking for tools that can do real/floating-point arithmetic, consider bc or awk . Whiskeyjack briefly discusses these in his recent episode ( Hacker Public Radio 4678 ) about high resolution timing. I don't consider either of them to be UNIX Curios, so I don't expect to talk about them in the future. References: First Edition UNIX dc manual page https://man.cat-v.org/unix-1st/1/dc Bc specification: Rationale https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html#tag_20_09_18 Expr specification https://pubs.opengroup.org/onlinepubs/9699919799/utilities/expr.html GNU multiple precision arithmetic library https://en.wikipedia.org/wiki/GNU_Multiple_Precision_Arithmetic_Library Test specification (2024) https://pubs.opengroup.org/onlinepubs/9799919799/utilities/test.html Test specification (2017) https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html PWB1 expr manual page https://www.tuhs.org/cgi-bin/utree.pl?file=PWB1/usr/man/man1/expr.1 PWB/UNIX https://en.wikipedia.org/wiki/PWB/UNIX Seventh Edition UNIX expr manual page https://man.cat-v.org/unix_7th/1/expr Seventh Edition UNIX test manual page https://man.cat-v.org/unix_7th/1/test Eighth Edition UNIX ksh manual page https://man.cat-v.org/unix_8th/1/ksh Tenth Edition UNIX sh manual page https://man.cat-v.org/unix_10th/1/sh X/Open CAE Specification: Commands and Utilities Issue 4, Version 2 https://pubs.opengroup.org/onlinepubs/009656399/toc.pdf An introduction to the C shell (2BSD) https://www.tuhs.org/cgi-bin/utree.pl?file=2BSD/doc/csh Appendix This shell script shows how one could perform either an arithmetic or string "less than or equal to" comparison using test based on the values of the two operands $a and $b . It makes a string comparison if either operand is null or contains characters other than decimal digits. Otherwise, it does a numerical comparison. It behaves the same as expr -- "$a" \<= "$b" , except that expr also writes "1" or "0" to standard output depending on whether the comparison is true or false and the fact that = in test means "is identical" rather than "collates the same". I assume you don't care about those, and also that the version of test you have supports the < and > operators. case "x$a" in x*[!0-9]*|x) test "$a" \< "$b" || test "x$a" = "x$b" ;; *) case "x$b" in x*[!0-9]*|x) test "$a" \< "$b" || test "x$a" = "x$b" ;; *) test "$a" -le "$b" esac esac If you really do want a "1" or "0" sent to standard output, you could use the following, though things are getting rather complicated at this point. Despite the complexity, it still doesn't handle situations where an error occurs. case "x$a" in x*[!0-9]*|x) test "$a" \< "$b" && echo 1 || { test "x$a" = "x$b" && echo 1 ; } || \ { echo 0 ; false ; } ;; *) case "x$b" in x*[!0-9]*|x) test "$a" \< "$b" && echo 1 || { test "x$a" = "x$b" && echo 1 ; } || \ { echo 0 ; false ; } ;; *) test "$a" -le "$b" && echo 1 || { echo 0 ; false ; } esac esac Provide feedback on this episode.

  • August 17 · length unknown

    HPR4706: Quirks and Customisations

    This show has been flagged as Clean by the host. System Quirks & Tweaks System Info:- CPU: 16-core AMD Ryzen 9 3950X (-MT MCP-) speed/min/max: 2433/2200/4761 MHz Kernel: 6.8.0-134-generic x86_64 Up: 18h 28m Mem: 17.58/62.73 GiB (28.0%) Storage: 3.64 TiB (81.9% used) Procs: 616 Shell: Bash inxi: 3.3.34 Some of the hacks:- Shell & Terminal Setup Visual Host Identifiers: I use custom terminal prompt colors and styles on different boxes so I can immediately see which machine I am logged into. Command Line Overrides: Standard tools are aliased to modern alternatives ( cat to batcat , df to duf , du to dust , ls to eza ). Word-Break Tweak: My shell config strips - and . from word-break rules so tab-completion handles hyphenated or dotted filenames as single words. History Search: I mapped Ctrl+F (instead of Ctrl+R ) to run a custom, colorized, interactive fuzzy history search using fzf . Local AI Tooling: I use AI coding interfaces, with ollama aliased to run Qwen Coder by default. Complex Toolchains: My system runs multiple co-existing environments, including conflicting Java runtimes (8 and 17), Android SDK, Rust, Go, and local Perl/Python libraries. Autostart & Background Services Audio & RGB Tweaks: Custom services handle Bluetooth switching for my Bose QC35 headphones, and cycled my keyboard lighting profiles based on the time of day. Passive Time Tracker: A custom background system tracks files via inotifywait and polls network connections to log my work hours into a 15-minute rounded log file. Typo Alert Keylogger: A root-owned background script buffered my keystrokes globally to run a spellcheck, firing a desktop alert when I made a typo. Work/Life Balance: Discord is configured to launch only on weekends or after 17:30 on weekdays. Custom Applications & Launchers Local LLM Voice Assistant: A desktop launcher opened "Marvin," a private local voice-chat assistant. Custom Remote Control: A custom script used ADB and Monkeyrunner to mirror and control an Android tablet screen in a local window. KWin Layout Fixes: Joplin is set to bypass the taskbar. Custom Panel Widgets Weather & Brightness: Custom scripts feed my desktop panel with weather emojis from the 7Timer! API and let me change external monitor brightness using ddcutil over I2C. Notification Pipelines: Custom shell scripts polled for SMS and email alerts, using MD5 hashes of the text blocks to ensure I never got duplicate notifications. Fake GPS Server: A tiny local server on port 22222 returns my home coordinates to any local app requesting geolocation. Repurposed "Radio" Panel Hardware Recycling: An old Android tablet with a broken screen is used as a green-screen terminal. It runs a custom WebView app to display ambient data. Gmail Push Pipeline: A local PHP script runs via cron every 10 minutes to fetch new email alerts and send them to the tablet over the local network. Provide feedback on this episode.

  • August 14 · length unknown

    HPR4705: Free Software Is Wasted On You Teens

    This show has been flagged as Explicit by the host. Freedom 0–3 (verbatim reference) The four freedoms, GNU/FSF: https://www.gnu.org/philosophy/free-sw.html Richard Stallman: https://www.stallman.org/ Named FOSS figures (freedom 3 list) Linus Torvalds (Linux): https://en.wikipedia.org/wiki/Linus_Torvalds Dries Buytaert (Drupal): https://dri.es Guido van Rossum (Python): https://gvanrossum.github.io Ian Murdock (Debian): https://en.wikipedia.org/wiki/Ian_Murdock Brian Behlendorf (Apache): https://en.wikipedia.org/wiki/Brian_Behlendorf Miguel de Icaza (GNOME/Mono): https://en.wikipedia.org/wiki/Miguel_de_Icaza Infrastructure block (post beer 1) curl / Daniel Stenberg: https://curl.se and https://daniel.haxx.se xkcd 2347 (dependency comic): https://xkcd.com/2347/ xz backdoor, CVE-2024-3094: https://en.wikipedia.org/wiki/XZ_Utils_backdoor Andres Freund's original disclosure: https://www.openwall.com/lists/oss-security/2024/03/29/4 Licensing block (beer 2–3) GPL: https://www.gnu.org/licenses/gpl-3.0.html MIT License: https://opensource.org/license/mit FreeBSD: https://www.freebsd.org macOS/Darwin BSD lineage: https://en.wikipedia.org/wiki/Darwin_(operating_system) PlayStation using FreeBSD (Orbis OS): https://en.wikipedia.org/wiki/Orbis_OS Industry acquisitions (beer 4) Microsoft acquires GitHub, 2018, $7.5B: https://news.microsoft.com/2018/06/04/microsoft-to-acquire-github-for-7-5-billion/ FOSDEM field report (beer 4–5) FOSDEM: https://fosdem.org Ladybird browser / Andreas Kling: https://ladybird.org Godot Engine: https://godotengine.org Home Assistant: https://www.home-assistant.io Redis → Valkey fork: https://valkey.io Terraform → OpenTofu fork: https://opentofu.org Homework block (beer 5) Ollama: https://ollama.com Codeberg: https://codeberg.org LibreOffice: https://www.libreoffice.org Firefox: https://www.mozilla.org/firefox Provide feedback on this episode.

  • August 13 · length unknown

    HPR4704: HPR Beer Garden 17 - Double DDH IPAs

    This show has been flagged as Clean by the host. In the seventeenth episode of the HPR Beer Garden, the guys look at a beer style (or label) that has recently appeared from across the pond: DDH IPA. Kevie tries out Smug DDH IPA by Northern Monk , Paul samples Hazy Jaipur by the Thornbrige Brewery and Dave enjoys Pinball by Brewdog . Connect with the guys on Untappd : Dave Paul Kevie The intro sounds for the show are used from: https://freesound.org/people/mixtus/sounds/329806/ https://freesound.org/people/j1987/sounds/123003/ https://freesound.org/people/greatsoundstube/sounds/628437/ The next 3 beer styles to be reviewed: Amber Ale Lager Mild Provide feedback on this episode.

  • August 12 · length unknown

    HPR4703: Ebooks and Audiobooks

    This show has been flagged as Clean by the host. I tend to prefer Ebook and Audiobooks to physical books, and these are some of the apps I use, and some of the sources I go to to find Ebooks or Audiobooks. These can be inexpensive, or in the case of Public Domain, free. Ebooks and Audiobooks I no longer wish to devote space to accumulating and storing physical books. As a former college professor I had more of them than most people, and tended to fill the house with bookcases and shelves. That made a certain sense in the pre-Internet years since I would often want to go back to them to look up things. But now I have more information at my fingertips than I ever had in those days, and I find it more convenient to just look up anything I need to know. And with Ebooks I can take my library with me anywhere I go. This means if I am sitting in a waiting room for a Doctor’s appointment (and at my age that happens often enough) I can just pull out my phone and open up a book. I always have at least one. Right now on my phone I have apps for Kindle , Google Play , Barnes & Noble Nook , Kobo Cantook (successor to Aldiko), Bookshop.org , and Calibre . As for devices other than my phone, I own a kindle, I once owned a Nook, and I will buy a Kobo reader when Trump is gone. Kobo is Canadian, and last time I looked Trump had put on a tariff that was twice what the device costs. And finally I have the Bookshop.org app and Calibre. I started collecting Ebooks some years back, and at first the only option seemed to be buying them from large corporations. That has changed now, but I still have collections On Kindle, Google Play, Nook, and Kobo. I have all four because it seemed prudent to not put all my eggs in one basket. But now there are other options. One I like to use when possible is Bookshop.org. It is group of independent bookstores and I would rather support them than some giant corporation. And they seem to have all of the popular titles. Another similar site is Books-a-Million , which lets you order online and pick up at a local store if you need a physical book. Cantook and Calibre are both good for holding any miscellaneous Ebooks you have, and you can give them your Ebooks from the other sellers, though I have found that the native apps tend to work better. These days I rarely purchase books on Kindle, etc. But sometimes they have a special deals. If you want to build your library, there are some good places to try. One is BookBub which will send you emails with deals on books. On any one e-mail you may not see anything you want, but I found that once or twice a month I did see books I wanted and at good prices. And Books-a-Million has 99 cent deals to check out. But if you want to get free books, you have several options. If you want a chance to read a popular Ebook but don’t need to own it, see what your local Library offers. Mine offers Hoopla which is good for Ebooks, Audiobooks, and streaming music. What you can find depends on what your library has in its collection, but my wife uses it almost daily for audiobooks. Then there are the works that have become part of the Public Domain. This varies somewhat by your country, but you might be surprised to learn how much is available. For Ebooks one of the biggest sites is Project Gutenberg . They follow US Copyright law for their collection, and they are a non-profit that can always use some support, so if you use them, give them a few Dollars or Euros. They tend to be the source for many or most other sites for Public Domain Ebooks They have over 75,000 free Ebooks. A newer site is Faded Page which is much smaller but focused on Canadian works. Standard Ebooks is a site that pulls from Project Gutenberg but does some additional formatting and is very easy to read online in your browser. For Audiobooks a good source is Open Culture , which advertises it has 1,000 free Audiobooks. We should also mention LibriVox , which also pulls from Project Gutenberg for its texts, but then turns them into Public Domain Audiobooks. They are always looking for volunteers who have a microphone and a computer to record Public Domain audiobooks. And last but not least the Internet Archive has tons of Ebooks and Audiobooks that are free. Links https://www.amazon.com/kindle/ https://play.google.com/store/books?hl=en_US&pli=1 https://www.barnesandnoble.com/b/ebooks-nook/_/N-8qa https://www.kobo.com/us/en?srsltid=AfmBOoquJmiNH_aVTUx22AIRlBH8CF4iir4H8qpTKjQ4dZ-fSMCDAaD7 https://market.cantook.com/ https://bookshop.org/ebooks https://calibre-ebook.com/ https://www.booksamillion.com/ https://www.bookbub.com/ https://www.hoopladigital.com/ https://www.gutenberg.org/ https://www.fadedpage.com/ https://standardebooks.org/ https://www.openculture.com/freeaudiobooks https://librivox.org/ https://archive.org/ https://www.palain.com/ebooks-and-audiobooks/ Provide feedback on this episode.

  • August 11 · length unknown

    HPR4702: MakeACopy is an open-source document scanner app for Android

    This show has been flagged as Clean by the host. MakeACopy MakeACopy is an open-source document scanner app for Android that allows you to digitize paper documents with OCR functionality. The app is designed to be privacy-friendly, working completely offline without any cloud connection or tracking. Features Camera Scanning : Capture documents using the device camera Edge Detection : Automatic document edge detection using OpenCV, enhanced with an ONNX model (DocAligner) Perspective Correction : Adjust and crop documents with manual or automatic perspective correction Image Enhancement : Apply filters (grayscale, contrast, sharpening) OCR : Offline text recognition with Tesseract OCR Review : Interactive review and correction of OCR results with word-level editing, dictionary-based suggestions, confidence highlighting, and re-OCR for individual words PDF Export : Save as searchable PDF with recognized text JPEG Export : Export scans as high-quality JPEG images (configurable quality, color/BW) Multi-page Scanning : Combine multiple pages into one document; reorder and manage pages before export Last Scans : Quickly access and reuse your most recent scans Share & Save : Export locally or share with other apps Dark Mode : Material 3 theme with day/night support Privacy-Focused : 100% offline functionality, no internet connection required Provide feedback on this episode.

  • August 10 · length unknown

    HPR4701: Elsbeth muses with Lee on her experiences and opinions on AI

    This show has been flagged as Explicit by the host. Overview: Elroy sits down with Elsbeth to unpack her perspective on AI ethics — where the technology helps, where it risks harm, and what responsible use actually looks like in practice. Topics covered (In no particular order, as the rabid squirrels of Elsbeth's AuDHD brain don't do "order"): Elsbeth's path into AI evaluation and content moderation, and how that shaped her thinking on ethics in practice What "ethical use" of AI means day-to-day, not just in the abstract Respecting intellectual property — the case for protecting artists and creators as AI tools become more capable and widespread Finding the balance: supporting AI's genuine benefits without letting them come at creators' expense AI as an accessibility tool — its particular promise for neurodivergent people, and where it can lower barriers others don't face Where the conversation is heading next, and what listeners should watch for Closing thoughts: Elsbeth's take is one of cautious optimism — a call to hold both truths at once: AI can do real good, and that good has to be built on respect for the people whose work made it possible. Further Reading & Resources On AI, Ethics, and Intellectual Property AI and Intellectual Property in 2026: why transparency and court rulings will define the next phase of governance — The AI Journal https://aijourn.com/ai-and-intellectual-property-in-2026-why-transparency-and-court-rulings-will-define-the-next-phase-of-governance/ Global laws governing intellectual property rights for AI-generated works — Discover Artificial Intelligence, Springer Nature Link https://link.springer.com/article/10.1007/s44163-026-01165-8 AI and IP laws 2026: Understanding Authorship and Ownership legalities — AnalystIP https://analystip.com/ai-and-ip-laws-2026-authorship-ownership-explained/ AI Art in 2026: The Ethics, Law, and What Artists Should Know — UrduPure https://www.urdupure.com/blog/ai-art-in-2026-the-ethics-law-and-what-artists-should-know On AI and Neurodivergent Accessibility Navigating Neurodivergence with AI Chatbots: Benefits, Tensions, and Implications for HCI — CHI 2026 Conference Proceedings https://dl.acm.org/doi/10.1145/3772318.3791334 Is AI making work more accessible for neurodiverse people? — Everway https://www.everway.com/en-gb/blog/is-ai-making-work-more-accessible-for-neurodiverse-people/ Autoethnographic Insights from Neurodivergent GAI "Power Users" — NCBI/PMC https://www.ncbi.nlm.nih.gov/pmc/articles/PMC12645485/ A scoping review of inclusive and adaptive human–AI interaction design for neurodivergent users — Disability and Rehabilitation: Assistive Technology https://www.tandfonline.com/doi/full/10.1080/17483107.2025.2579822 Show rated *explicit* for possible course language and strong opinions. Provide feedback on this episode.

  • August 7 · length unknown

    HPR4700: Robert A. Heinlein: The Juveniles

    This show has been flagged as Clean by the host. Heinlein wrote a series of books under contract to Scribners that were aumed at younger readers, pre-teen and teen. Today we would call them Young Adult, but back then they were called Juveniles. But even an adult reader can enjoy many of these books. Because they were aimed at younger readers, he could not always be as explicit as he might have liked, but if you pay attention you just might noticed he slipped in something subversive. Heinlein: The Juveniles As a boy I read voraciously. I remember my mother organizing weekly trips to the town library, where I would load up on books, and I quickly became focused on Science Fiction, along with the usual stuff kids read, like the Hardy Boys, Tom Swift, and the Walter Farley horse books. But the idea of going into space grabbed me very early. And one of the first authors I read was Heinlein. He had taken a leave from publishing during World War II, when he was doing research at the Philadelphia Navy Yard. But when the war was over, he set out to move beyond the “pulps” and expand the market for his stories. And one big market for him was what were called “juveniles” at the time, and would today be called “Young Adult”. I was reading adult fiction by the time I was 11 or 12, but before that (and even after that, in fact) I read these Heinlein novels with great relish. Heinlein’s target audience for these novels was teenage boys. He did a few stories aimed at girls, but mostly he wrote for boys. And these were mostly “coming of age” stories where the teenage protagonist has adventures, and as a result grows and develops. They are very loosely related via some internal references, but should really be thought of as stand-alone stories. They also in some cases have references to his other stories, including the Future history stories. He wrote 13 of these novels, one per year, from 1947 to 1959. The series was published by Scribners until the last one was rejected by them. Heinlein then published it with a different publisher, and stopped writing these novels altogether in favor of more adult fiction. The novels roughly form a progression telling the story of space exploration. It starts with a trip to the Moon, then Venus, Mars, Jupiter’s moon, and so on until we reach the Lesser Magellanic Cloud. Rocket Ship Galileo (1947) – While readable, this initial effort was not up to Heinlein’s later standards. The plot concerns three teenagers who assist an uncle to build a rocket ship and go to the Moon. When they get there they discover Nazis have already arrived. The Nazis try to kill the group, but they succeed in turning the tables, stealing the Nazi ship, and returning to Earth as heroes. This novel became the basis (loosely) for the movie Destination Moon (1950), and I personally would consider the movie to be superior to the novel. It is also worth noting that the theory brought up in Blowups Happen reappears in this novel. They find evidence of an ancient Lunar civilization that was destroyed, and theorize that the craters on the moon were caused by the explosion of nuclear reactors that caused the extinction of the civilization. Space Cadet (1948) – This was in part the inspiration for the Tom Corbett franchise, which licensed the name Space Cadet from Heinlein. It is about a young man who is accepted to the Academy for the Space Patrol. It follows him through his education in the Academy, and then into his first mission after graduating. This holds up better than the previous novel. And it is tied back to the story The Long Watch from the Future History. Part of the story takes place on an inhabited Venus that is cloudy and swampy. Red Planet (1949) – This is set on Mars, as it is also portrayed in Stranger In A Strange Land (1961). Mars is inhabited by native Martians, but also by human colonists. It has the canals, and with seasonal changes the colonists migrate from north to south and back. A pair of teenage boys get caught up in a revolution when the evil corporation that controls the colony pushes the colonists too far. In the end you wish there really were canals and Martians. Farmer In The Sky (1950) – This is one of the best, as seen by the Retro Hugo this novel won in 2000. Jupiter’s moon Ganymede is being terraformed because Earth is overcrowded and food is rationed. A teenage boy and his family emigrate to Ganymede and try to make a life there, which they eventually succeed in doing. The Green Hills of Earth is mentioned here, tying this into the future History. There are frequent references to the Boy Scouts, due to the fact that the story ran as a serial in Boy’s Life magazine. Between Planets (1951) – A teenage boy is caught up in interplanetary intrigue. Venus and Mars have colonies, but Earth is trying to control them too much. So revolution is on the menu. This is clearly patterned in the colonial wars of the 18th and 19th centuries, such as the American Revolution against England. By this point the so-called “Juveniles” are really having more adult content, and reviewers re starting to rate them in comparison with adult science fiction. This novel was also first serialized in Boy’s Life magazine. The Rolling Stones (1952) – Here we have teenage twin boys, Castor and Pollux, as the protagonists. They and their family live on the Moon, but decide to travel, so this novel is a kind of travelogue as they go to Mars, then to the Asteroid belt. The grandmother, Hazel Stone, appears in Heinlein’s later works as well. One interesting episode in this story involves “martian flat cats”, which are furry, lovable, and reproduce like mad with the right conditions. If this sound like Star Trek’s Tribbles, that is also what the Star Trek producers thought, so they got permission from Heinlein to use the idea. Starman Jones (1953) – We are now further into the future, and the human race is exploring the stars. Unfortunately, very restrictive guilds closely control who can participate in this. A teenage boy named Max, who happens to have an eidetic memory, has memorized the Astrogation tables from his uncle’s books, and wants to join the Guild, but is turned down. He lies his way onboard a ship, and through a series of events becomes the only one who can guide the ship home. The Star Beast (1954) – A teenage boy has an alien “pet” his great-grandfather had brought back that has grown very large, and is considered a nuisance. A court decides the beast must be killed, but that proves easier to say than to do. It appears that the beast isn’t even aware that people are trying to kill it. Meanwhile, a powerful and hitherto unknown alien species demand the return of one of their own, or they will destroy the Earth. Of course, it is this beast, who is actually royalty to the alien species. One interesting point is that government officials in this story are portrayed sympathetically as intelligent and dedicated. Tunnel In The Sky (1955) – In the future humanity is colonizing other planets, and a group of teenagers are taking their final survival test. They are sent to a planet and told that they have to survive for 10 days, But more than 10 days go by with no pickup, and they know something went wrong. So they have to establish their own little society to keep surviving. An interesting note is that the protagonist, Rod Walker, is black. It was never explicitly stated in the text, but Heinlein was firm in stating this. The clue is when the others expect Rod to end up with Caroline, who is explicitly stated to be black. This was Heinlein being subtly subversive. To have a black protagonist for a boy’s story in 1955 in America would be impossible. but Heinlein was completely anti-racist, among other things. Time For The Stars (1956) – This is a novel that takes Relativity seriously, which was not common in the 1950s. Researchers have discovered that some twins and triplets can communicate telepathically (and instantaneously), and so when a group of ships is sent out to explore other star systems, one twin is on the ship and the other remains on Earth to provide communication. The twin on Earth ages must faster than the one in space, of course, and eventually the Earth twin dies, But they discover that the connection sometimes passes down through the family, so the protagonist, Tom Bartlett, becomes connected first to his niece, then his grandniece, and finally his great-grandniece. Citizen of the Galaxy (1957) – This book is about a future slave trade, which Heinlein strongly hated. The protagonist is a boy who is bought at a slave auction by an old beggar, but the beggar is more than he seems. He is actually spying and gathering data regarding the slave trade. When discovered, he commits suicide, but he had prepared the young boy, Thorby, who then contacts the Free Traders who spirit him away. He has to adapt to this new society, but then is delivered to the Hegemonic Guard. It turns out his “father” (i.e. the man who bought him) was an officer in this organization. And when they run the background checks, they discover that he is the heir to a large conglomerate, and that conglomerate may be implicated in the slave trade. Have Space Suit—Will Travel (1958) – Clifford “Kip” Russell dreams of going to the Moon, and enters a contest with that as the top prize. Unfortunately, he wins the somewhat lesser prize of a used spacesuit. The first few chapters focus on him doing repairs and maintenance to make it functional again, and this displays Heinlein’s engineering background. It is more engaging than you might think. Then while wearing the spacesuit he receives a radio message, and he is kidnapped along with an alien called “The Mother Thing” and a young girl who is a genius. The kidnappers are a group of aliens who consider anyone not of their race to be animals. The trio first try to escape on the Moon, but are recaptured, then taken to Pluto, where they succeed in killing the alien kidnappers. Then they are taken to the Lesser Magellanic Cloud to be put on trial to determine if the human race should be allowed to live. Starship Troopers (1959) – This is the novel that Scribners rejected, and which brought the Juvenile series to an end. And it bears absolutely no resemblance at all to the movie, to the point that for Heinlein fans the word Verhoeven is considered an obscenity. A young man, Juan “Johnny” Rico joins the military, where he has to grow up and then take part in a war against an insectoid race, but that is all background really. The book is primarily a glorification of military service, which is not surprising given Heinlein’s background. And it focuses on a series of discussions under the heading of “History and Moral Philosophy”, which lets Heinlein expound on his values and beliefs. The novel won a Hugo, but it is an add one given that the plot is secondary to the philosophizing. One of the most controversial ideas is that in this society the right to vote is limited to people who have been in Federal Service. Heinlein said this didn’t have to be military, but the only ones we see are in fact military veterans. So, these are the Heinlein Juveniles. In my opinion, many of them are quite good reading for adults. The thing that separates them from adult novels in Heinlein’s body of work is the lack of any sex element. That would become prominent in Heinlein’s later adult novels, but it was not something you could put in a book aimed at teenagers, certainly not in the 1950s, and arguably the case today as well. Links https://en.wikipedia.org/wiki/Rocket_Ship_Galileo https://en.wikipedia.org/wiki/Destination_Moon_(film) https://en.wikipedia.org/wiki/Space_Cadet https://en.wikipedia.org/wiki/Tom_Corbett,_Space_Cadet_(TV_series) https://en.wikipedia.org/wiki/Red_Planet_(novel) https://en.wikipedia.org/wiki/Stranger_in_a_Strange_Land https://en.wikipedia.org/wiki/Farmer_in_the_Sky https://en.wikipedia.org/wiki/Scout_Life https://en.wikipedia.org/wiki/Between_Planets https://en.wikipedia.org/wiki/The_Rolling_Stones_(novel) https://en.wikipedia.org/wiki/Starman_Jones https://en.wikipedia.org/wiki/The_Star_Beast_(novel) https://en.wikipedia.org/wiki/Tunnel_in_the_Sky https://en.wikipedia.org/wiki/Time_for_the_Stars https://en.wikipedia.org/wiki/Citizen_of_the_Galaxy https://en.wikipedia.org/wiki/Have_Space_Suit%E2%80%94Will_Travel https://en.wikipedia.org/wiki/Starship_Troopers https://www.palain.com/science-fiction/the-golden-age/robert-a-heinlein/heinlein-the-juveniles/ Provide feedback on this episode.

  • August 6 · length unknown

    HPR4699: Sunshine, Moonlight, Playnite !?

    This show has been flagged as Clean by the host. sunshine / xbox contlers / plex / steam / UWPHook / Bluetoothctl restart / HDMI dongle https://www.youtube.com/watch?v=FM4FbA4-W_c UGREEN USB C Hub 5 in 1 Multiport Adapter Revodok 105 4K HDMI, 100W Power Delivery, 3 USB-A Data Ports, USB C Dongle for MacBook Pro/Air, iPad Pro, iMac, iPhone 16 Pro/Pro Max, XPS, Thinkpad https://www.amazon.com/dp/B0BR3M8XHK Detached Command: @ECHO OFF cd "C:\backup\gamestream_launchpad" c:\windows\System32\HdrSwitcher.exe disable start /MIN gamestream_launchpad.exe 1920 1080 gamestream_playnite.ini .bindkeys rc cat .xbindkeysrc /bin/bash /home/plex/.local/bin/Plex.sh /bin/bash /home/plex/.local/bin/Steam.sh /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer on; /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer brightness 100;xgamma -gamma 1.3 /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer on; /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer brightness 40;xgamma -gamma 1.3 /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer on; /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer brightness 12;xgamma -gamma 1.3 /home/plex/.local/bin/kasa --host 192.168.1.239 --port 9999 --type dimmer off;xgamma -gamma 1.3" cat /home/plex/.local/bin/Steam.sh # requires wmctrl -l and xbindkeys # # xdotool windowactivate ```xdotool search --name 'window name'``` # 0 StartSteamLink(){ echo "restarting bluetooth" sudo systemctl restart bluetooth echo "Waking Game PC" sudo /usr/sbin/etherwake -i enp1s0 -D "d8:bb:c1:a2:2c:0b" echo "Starting steamlink" killall -9 steamlink killall moonlight sleep 20 # /snap/bin/moonlight /home/plex/.local/bin/Moonlight-6.1.0-x86_64.AppImage } StartSteamLink SUMMARY: Speaker discusses technical challenges with Sun Shine, Moonlight, and Play Night setups. IDEAS: Sun Shine and Moonlight enable remote game streaming. Play Night acts as a multimodal launcher for Steam. Resolution changes cause display issues during gameplay. Proper exit sequence is critical to revert settings. Ultra-wide resolutions are unusable in some configurations. Multiple launchers require separate logins for different games. Environment variables can adjust client dimensions. Background commands improve system stability. Cat named Mojo is mentioned during the discussion. 5G networks support slower-paced gaming. Technical glitches include frame drops and latency. Steam accounts are tied to specific game libraries. Detached commands run in the background without user interaction. GameStream Launchpad manages resolution and launcher paths. Magical system behavior simplifies remote gaming. Star Wars and Baldur’s Gate are cited as example games. 22nd Millie thing refers to network latency. Multiple Steam accounts complicate game access. Task killing reverts system settings automatically. Cross-platform streaming solutions are highlighted. RECOMMENDATIONS: Use environment variables for client resolution adjustments. Exit applications properly to revert settings. Set up detached background commands for stability. Monitor ultra-wide resolution compatibility. Utilize Play Night for Steam account management. Avoid multiple logins for different game libraries. Opt for cross-platform streaming solutions. Check network latency for smooth gameplay. Use bat files for automated task execution. Configure GameStream Launchpad for resolution changes. Prioritize proper task termination to prevent glitches. Test 5G networks for slower-paced gaming. Leverage environment variables for client settings. Ensure all applications exit before shutting down. Use detached commands for background processes. Verify resolution compatibility with ultra-wide displays. Combine Sun Shine and Moonlight for reliable streaming. Log in once for multiple Steam accounts. Address frame drops in low-latency networks. Stream games universally across platforms. Provide feedback on this episode.

  • August 5 · length unknown

    HPR4698: ID3 Tags and Vorbis Comments

    This show has been flagged as Clean by the host. -------------------- 01 Introduction In a response to a post on a previous episode, I said that I would take a look at ID3 tags. ID3 tags are text information that is added to an MP3 audio file, such as the author, date, name, and other information. 02 While I am at it I will also look at Vorbis comments, which perform a similar function for vorbis, the container format for "ogg" audio files. As example audio files, I will use a recent HPR episode, hpr4678 in both mp3 and vorbis formats plus also one from another podcast as well. 03 There is Free Software which you can use to view, edit, or remove both types of tags or comments, and I will describe how to use it in this episode. 04 I will cover how to view tags and extract the text information, as well as how to strip the tags from a file and why you may wish to do so under certain very specific circumstances. I won't cover how to add to or edit tags in an MP3 or OGG file, as that is a more involved subject that I don't have much experience with. 05 I will mainly talk about ID3 MP3 tags rather than vorbis comments for the simple reason that the situation with MP3 files is an utter mess while vorbis comments are very straightforward and so there isn't as much to say about them. 06 As often happens when researching a subject to write a podcast script, I have learned quite a bit that I didn't know previously, and discovered that things that I thought I did know were wrong. I hope that you may learn a few things from this episode that you didn't know previously either. -------------------- 07 Background I won't go over the detailed history of ID3 tags, as I don't have a reliable source for this. Briefly however, so far as I can determine, there is no official independent standard for ID3 tags or vorbis comments. Both seem to be more in the nature of a convention that was created by an unofficial group of contributors rather than something issued by a standards body. 08 However, I don't see the lack of a conventional standards body as necessarily a problem with respect to the use of ID3 tags or vorbis comments. I just am not familiar enough with the industry to know who to regard as being an authoritative source when it comes to the history and development of them Since I am unsure as who to credit with what developments, I will avoid that sort of detail. 09 ID3 Tags There is a web site with the URL of ID3.org that seems to have the best reference material on the topic of ID3 tags. According to this site, the term "ID3" means "IDentify an MP3". 10 Vorbis Comments For vorbis, the reference site seems to be xiph.org. Although the implementation details may differ from ID3, from our perspective as podcast listeners, they can be seen as more or less equivalent in terms of what I am going to address here. -------------------- 11 ID3 Details Versions One of the problems with ID3 is that there are multiple incompatible versions, particularly from the very early days. ID3v1 tags are located at the end of the audio file in the last 128 bytes. This was done for compatibility reasons to allow early MP3 players to simply ignore the tags if they didn't know how to deal with them. The tags would simply appear as a short burst of static from the perspective of these early players. 12 ID3v2 moved the tags to the start of the MP3 file to allow players to scan the tags for information such as titles without having to read to the end of the file to find them. There are far fewer limits on the amount of information that can be placed in ID3v2 tags. 13 ID3v1 is obsolete and only very old players will require it. However, it is still used by some publishers for backward compatibility reasons. ID3v1 included numerical musical "genre" category codes which apparently turned out to be a very bad idea in practice. 14 Furthermore, all genre categories above 70 were defined by an audio software company called Nullsoft who created software such as Winamp. These codes were never actually part of the ID3 standard, although there was never really a standard to begin with. 15 The current ID3 version is 2.3. There is a version 2.4, but apparently it is not actually generally accepted and may be a developmental dead end. 16 The id3.org web site contains a copy of the ID3v2.3 standard, but I am not going to address the technical details here. This would only be of interest to someone who was creating software to read and write ID3 tags. 17 ID3v2 Frames The ID3v2 information is encoded into what are called "frames". The text information is contained in text information frames. 18 Text information frames start with a set of four character identifiers, all starting with the capital letter 'T'. Examples "TALB" is the "Album/Movie/Show title" frame. "TIT2" is the "Title/Songname/Content description" frame. "TYER" is the "Year" frame. There are many more, but I won't go into more detail here. 19 HPR ID3 Tags HPR makes an interesting case study because they use both ID3v1 and ID3v2 in the same file. This can cause some interesting problems with software that tries to read those tags. This is because most software appears to expect one or the other, but not both. However, so long as this does not cause problems with anything that actually plays the files, this is not a problem so far as people who just want to listen to podcasts are concerned. It does mean though that we have more to talk about than we would otherwise would have had. -------------------- 20 Vorbis Comment Fields The situation with Vorbis comments is much simpler, as there seems to be just one standard that was adhered to from the start rather than a succession of hacks. Information is stored in "fields", which xiph describes as being like Unix environment variables. These consist of a field name followed by an equal sign and then the information intended for that field. Field names are case insensitive. 21 The field names are not firmly defined at this stage, but there is a list of recommended names. Examples are "TITLE" is the Track or Work name. "ARTIST" is the person responsible for the work. "LICENSE" is the license information. 22 You can see the complete list for yourself on the comment field and header specification page at xiph.org -------------------- 23 Software for Listing, Adding, and Modifying Tags and Fields There are three software packages that I will now describe which allow you to list, add, modify, and remove tags and fields. There are other packages which can do the same, including some which offer a GUI interface. However, I will limit myself to describing these three. The principles should be the same for others. 24 ffprobe ffprobe is part of the ffmpeg package. If you have listened to my previous episodes on audio, you will have heard me talk about ffmpeg. ffprobe is used to display information about media files rather than for modifying them. ffprobe is licensed under the GPLv2 or later. ffprobe can be used to display information about both MP3 and OGG Vorbis files. 25 ID3v2 The next is the rather aptly named id3v2 and works with MP3 files. On Linux systems, this should be provided by the id3v2 package. On Debian derivatives this can be installed as follows sudo apt install id3v2 26 This also installs a man page which provides a brief list of the options. According to the README file in the source tarball, this is published under the LGPL ID3v2 is particularly useful for displaying ID3v1 tags. 27 vorbiscomment The third is "vorbiscomment" and works with OGG files. On Linux systems this should be provided by the "vorbis-tools" package. On Debian derivatives this can be installed as follows sudo apt install vorbis-tools 28 The vorbiscomment program is used to list or edit comments in Ogg Vorbis files. This also installs a man page which provides a brief list of the options. According to the license.lgpl file in the source tarball, this is published under the LGPL version2. 29 The display format for vorbiscomment follows the data definition format in the vorbis standard, whereas ffprobe re-formats it to match its own preferred appearance. -------------------- 30 Examples from HPR With the background out of the way, I will now give several examples of how to list the tags or fields. 31 Listing ID3v1 Tags As previously mentioned HPR uses both ID3v1 and ID3v2 tags in the same file. However, so far as I can tell, most software seems to look for ID3v2 tags first, and don't display the ID3v1 tags if both are present. 32 The ID3v2 program however seems to do the opposite, at least with HPR podcasts. However, the number of samples that I have which have both are rather limited, so I can't be sure if this is always the case or if this is a side effect of something else. I did mention that ID3 tags were a mess, didn't I? 33 Let's go on to our example however. If we want to see the ID3v1 tags, then using hpr4678 as an example, if we type id3v2 -l hpr4678.mp3 = we get the following result. 34 id3v1 tag info for hpr4678.mp3: Title : High Resolution Elapsed Time i Artist: Whiskeyjack Album : Hacker Public Radio Year: 2026, Genre: Unknown (186) Comment: https://hackerpublicradio.or Track: 0 hpr4678.mp3: No ID3v2 tag 35 The first line tells us that this information is ID3v1 tags. The last line tells us that there are no ID3v2 tags. This last line is incorrect, but we will come back to that later. 36 In between are three lines of text. The first line contains the title and the artist. The title is the name of the HPR episode, or at least part of it. The artist is the HPR contributor who made that episode. 37 The second line contains the album name, the year, and the genre. The album name is this case is simply Hacker Public Radio, as the concept of an album doesn't really fit a podcast. The year is the year that the episode was recorded, or at least the year in which the MP3 file was assembled with the HPR intro and the tags added. 38 The genre is listed as "unknown 186". Recall that with ID3v1 tags there is a one byte numeric genre code, but that no genres above 70 were ever officially assigned. It seems to be a general convention though to use a code 186 for podcasts. 39 The third line contain a comment and track number. The comment in this case is the HPR web site URL. The track is zero. "Track" would appear to serve no useful purpose in this instance. However, it may be there for reasons of compatibility that I am unaware of, so I would be very reluctant to remove that without very good reason. 40 If we look at the above information in detail we can see that two of the tags appear to have cut their text information off short. The title is cut off in mid word after the 30th character. The final "g" in "hackerpublicradio.org" is cut off in the comment. 41 Alternative Method for ID3v1 We can confirm whether the text being cut short is due to a problem with the id3v2 program, or whether it really represents the data in the file by using a rather simple check. 42 Recall that ID3v1 tags are simply the last 128 bytes of the MP3 file. All we need to do is to extract the last 128 bytes of the file. We can do this using the standard tail command. tail -c128 hpr4678.mp3 | tr '\0' ' ' | tr -c '[:print:]' 'x' 43 The -c128 option used with tail tells it to extract the last 128 bytes of the file. We then pass the result through the "tr" command and tell it to replace null bytes with new line characters. Then we replace any remaining non-printable characters with an 'x'. When we do that we get the following 44 TAGHigh Resolution Elapsed Time iWhiskeyjack Hacker Public Radio 2026https://hackerpublicradio.or x 45 The first three characters are capital TAG. This is a flag which indicates that what follows are ID3 tags. 46 Next, we have 30 characters which specify the title. The next 30 characters specify the artist. The next 30 characters are the album, or in this case just "Hacker Public Radio". The next 4 characters are the year. The next 30 characters are a comment, or in this case the HPR URL, except for the final "g". The last character is the genre code, which we have replaced with an "x" because it is otherwise non-printable. 47 Taken together, these add up to 128 bytes. We can see that the field lengths are of fixed length with pre-defined meanings based on position. -------------------- 48 ID3v2 Using ffprobe Now lets move on to ID3v2 tags, which is probably more useful for most people. For this, we will switch to using ffprobe. The command for this is ffprobe -hide_banner hpr4678.mp3 The -hide_banner option suppresses extra data about the codecs which doesn't interest us much and leaves mainly the tag information plus a few other things. 49 The output gives us the full data that is associated with the podcast episode from the HPR web site. This includes the episode number, year, full title, author, license, and full summary text. You can see a full copy of this in the show notes. Input #0, mp3, from 'hpr4678.mp3': Metadata: track : 4678 year : 2026 title : High Resolution Elapsed Time in Shell Scripts author : Whiskeyjack copyright : CC-BY-SA artist : Whiskeyjack album : Hacker Public Radio comment : https://hackerpublicradio.org Clean; Surprises encountered when measuring elapsed time in shell scripts The license is CC-BY-SA genre : Podcast encoder : Lavf61.7.103 date : 2026 Duration: 00:30:10.18, start: 0.023021, bitrate: 64 kb/s Stream #0:0: Audio: mp3, 48000 Hz, mono, fltp, 64 kb/s 50 The ID3v2 tag version contains all of the information which was provided by the author, including the full title and description without the 30 character limit of ID3V1. If you want any of this information for some reason you should be able to extract it from the MP3 file using a combination of ffprobe, grep, and cut rather than trying to scrape the HPR web site and matching it to the MP3 later. -------------------- 51 ID3v1 Using ffprobe I previously mentioned that HPR MP3 files have both ID3v1 and ID3v2 tags in the same file, and that ffprobe will default to using ID3v2 tags if present. However, what happens if we remove the ID3v2 tags and leave the ID3v1 tags? I will describe how to strip tags later on in this episode, but let's just assume for now that I have done this. If we then use ffprobe to read the ID3 tags using the same command as before, we get the following output. 52 We get a series of lines in the same format as with ID3v2, but with each data element limited to at most 30 bytes. These include title, artist, album, date, comment, and genre. You can see the full output in the show notes. Input #0, mp3, from 'test.mp3': Metadata: title : High Resolution Elapsed Time i artist : Whiskeyjack album : Hacker Public Radio date : 2026 comment : https://hackerpublicradio.or genre : Podcast Duration: 00:30:10.18, start: 0.023021, bitrate: 64 kb/s Stream #0:0: Audio: mp3, 48000 Hz, mono, fltp, 64 kb/s 53 The information is the same as when read by the id3v2 program, but formatted for display in the manner that ffprobe uses. This shows that ffprobe can indeed read ID3v1 tags if they are the only ones present. -------------------- 54 Reading Vorbis Comments Now let us turn our attention to vorbis comments, which are the equivalent to tags for ogg files. We will look at this using two methods. 55 Using vorbiscomment The first method we will look at is using the vorbiscomment package. The command is vorbiscomment -l hpr4678.ogg 56 The output of this is a series of lines with key value pairs separated by equal signs. The output is also exactly the same as the MP3 file, except that there is an additional "language" field, "track" becomes "TRACKNUMBER", and there is no "date" field. You can see the full output in the show notes. encoder=Lavc61.19.101 libvorbis TRACKNUMBER=4678 year=2026 language=English title=High Resolution Elapsed Time in Shell Scripts author=Whiskeyjack copyright=CC-BY-SA artist=Whiskeyjack album=Hacker Public Radio DESCRIPTION=https://hackerpublicradio.org Clean; Surprises encountered when measuring elapsed time in shell scripts The license is CC-BY-SA genre=Podcast 57 Using ffprobe Now lets do the same again using ffprobe. The command for this is ffprobe -hide_banner hpr4678.ogg 58 The output content is the same of course, but the field names have all been forced to lower case, and instead of an equal sign as a separator between the key and value, this has been replaced by a colon and white space has been added to make the output look a bit nicer. You can see the full output in the show notes. Input #0, ogg, from 'hpr4678.ogg': Duration: 00:30:10.14, start: 0.000000, bitrate: 86 kb/s Stream #0:0(English): Audio: vorbis, 192000 Hz, mono, fltp, 4294967 kb/s Metadata: encoder : Lavc61.19.101 libvorbis track : 4678 year : 2026 title : High Resolution Elapsed Time in Shell Scripts author : Whiskeyjack copyright : CC-BY-SA artist : Whiskeyjack album : Hacker Public Radio comment : https://hackerpublicradio.org Clean; Surprises encountered when measuring elapsed time in shell scripts The license is CC-BY-SA genre : Podcast -------------------- 59 Another Example from Another Podcast The above is interesting, but it's a sample of one podcast. Let's look at another different one altogether. For this test I used two episodes of the Linux Matters podcast, episodes 68 and 82. As to why I am using two different episodes I will explain in a moment. 60 Episode 68 We will start with examining episode 68 Using id3v2 The command using id3v2 is id3v2 -l LMP68.mp3 61 This provides output as a series of lines containing the official 4 character identifiers from the standard, a description of the identifiers, and the text provided by the authors. The identifiers include TIT2 indicating title, TALB indicating show title, TRCK indicating track number, and a number of others. You can see the full output in the show notes. id3v2 tag info for LMP68.mp3: TIT2 (Title/songname/content description): 68: Frameworks, Filesystems and Fixes TPE1 (Lead performer(s)/Soloist(s)): Linux Matters TALB (Album/Movie/Show title): Linux Matters TYER (Year): 2025 TRCK (Track number/Position in set): 68 COMM (Comments): ()[]: https://linuxmatters.sh/ APIC (Attached picture): (LMP-3000-moon.jpg)[, 3]: image/jpeg, 554576 bytes LMP68.mp3: No ID3v1 tag 62 From this we can see what the id3v2 program would normally do with ID3v2 tags. Note that it outputs the actual 4 character identifiers, plus a description of what they mean, and then the actual data. This helps when trying to understand the actual encoding of the data. 63 Using ffprobe Now let's try that with ffprobe. The command is ffprobe -hide_banner LMP68.mp3 64 This provides the same publisher provided data as before. However it does not display the 4 character identifiers but instead uses its own format for display. Also note in both cases that there is a picture embedded in the MP3 file which is used to generate an icon for display in your file manager. With ffprobe this results in there being two keys called "title" and two keys called "comment". This makes grepping for the metadata more complicated, but it should still be possible. You can see the full output in the show notes. Input #0, mp3, from 'LMP68.mp3': Metadata: title : 68: Frameworks, Filesystems and Fixes artist : Linux Matters album : Linux Matters comment : https://linuxmatters.sh/ track : 68 date : 2025 Duration: 00:28:12.45, start: 0.025056, bitrate: 114 kb/s Stream #0:0: Audio: mp3, 44100 Hz, mono, fltp, 112 kb/s Metadata: encoder : LAME3.100 Stream #0:1: Video: mjpeg (Progressive), yuvj444p(pc, bt470bg/unknown/unknown), 4166x4166 [SAR 72:72 DAR 1:1], 90k tbr, 90k tbn (attached pic) Metadata: title : LMP-3000-moon.jpg comment : Cover (front) 65 Episode 82 Now lets try that again with a different episode, 82. Using id3v2 The command for id3v2 is id3v2 -l LMP82.mp3 This results in id3v2 saying LMP82.mp3: No ID3 tag What happened here? 66 Using ffprobe Let's try that again with ffprobe. The command ffprobe -hide_banner LMP82.mp3 provides the expected output. Input #0, mp3, from 'LMP82.mp3': Metadata: date : 2026-05 title : 82: Ditching Grammarly for Open Sauce album : Linux Matters track : 82 artist : Linux Matters comment : https://linuxmatters.sh Duration: 00:33:37.83, start: 0.025056, bitrate: 113 kb/s Stream #0:0: Audio: mp3, 44100 Hz, mono, fltp, 112 kb/s Stream #0:1: Video: png, rgb24(pc, gbr/unknown/unknown), 3000x3000, 90k tbr, 90k tbn (attached pic) Metadata: title : Linux Matters Logo comment : Cover (front) 67 This results in a few minor changes from episode 68, but otherwise it looks the same. So there are ID3 tags, but for some reason id3v2 couldn't recognize them. A bit more research and experimentation shows that this change appears to have happened right after episode 68, when they changed hosting and processing arrangements. I suspect that something changed with respect to the ID3v2 tag formatting somewhere along the way in the change over, and this in turn has affected the ability of the id3v2 program to recognize the tags. I will come back to the implications of this later in my conclusions. -------------------- 68 Stripping ID3 Tags Now let's turn to a differen topic. Stripping ID3 tags refers to removing the ID3 tags from the audio file. I will start off by emphasizing that normally, you don't want to do this. You should only be doing it if you suspect the ID3 tags are causing a problem with the playback or ordering of the files. 69 In my case I do it when I have problems with my MP3 player when playing certain podcasts. This MP3 player orders files according to ID3 tags rather than by file name. This can result in the podcasts being played in an unpredictable order which I find undesirable. This is particularly a problem with podcasts from certain publishers where the title data does not follow any consistent pattern, but is whatever someone felt like doing that day. 70 I also often have to normalize the files from the same publishers to get a consistent audio loudness. See my series on Simple Podcasting for information on how to use ffmpeg to normalize the audio loudness. The solution to the inconsistent tag formats in these cases is to simply strip the ID3 tags altogether. The player then falls back on using the file names, and I can readily rename the files to a consistent format. I have never had these sorts of problems with HPR podcasts. If you are not having any problems of this nature, then as I said, don't bother stripping the tags. 71 To strip the ID3 tags from an MP3 file use the following. id3v2 -D hpr4678.mp3 id3v2 will strip the tags and overwrite the existing file. If you wish to keep a copy with the tags, be sure to keep a backup before you try things. 72 When it comes to stripping tags, the options are "-s" deletes ID3v1 tags. "-d" deletes ID3v2 tags. "-D" deletes both v1 and v2 tags. -------------------- 73 Conclusions In this episode we took a very brief look at ID3 tags and vorbis comments and ways of reading them. 74 ID3 tags and Vorbis comments provide a means of allowing information about an MP3 or OGG Vorbis file to be embedded in the file itself. Podcast publishers very often use this to label the file with information such as title, publisher, and author. We can read this information using Fee Software tools such as ffprobe, ID3v2, and vorbiscomment. 75 ID3 tags seem to be a mess with more than one incompatible versions, and difficulties in reading them even within the same version. They are difficult to test for because there is so much hardware out there of varying ages, much of which you will never have heard of let alone had access to. If you are recording episodes for HPR you do not have to worry about this, as HPR will do this behind the scenes for you. However, if you are responsible for producing a podcast or other similar audio and you have a setup that works, it is probably best not to change anything without good reason. 76 Vorbis comments seem to be much less of a problem. However, there are far fewer devices which can play OGG files compared to MP3, so simply switching to OGG may not be a realistic solution to the ID3 tag problem. 77 If you wish to have one tool that can read ID3 tags of all sorts and vorbis comments, then ffprobe is your obvious choice. 78 The ID3v2 program will provide more information about the ID3 tags, including the actual identifiers used. However, it does not work in all cases. 79 The vorbiscomment program will read Vorbis comments from OGG files in a manner which is closer to the actual vorbis format than ffprobe does, which uses its own display format. 80 HPR includes both ID3v1 and ID3v2 tags in its MP3 files. ffprobe can be used to read the ID3v2 tags, and the id3v2 program can be used to read the ID3v1 tags. You can also read the ID3v1 tags using the tail command. 81 I have barely scratched the surface of this subject and have not talked at all about creating tags or comments. If anyone else would like to take up the challenge of providing more detail, or of correcting any mistakes that have made, please send in a podcast episode on the subject. If you have any comments you would like to make, leave them in the comment section below this episode on the HPR web site. 82 I hope to see you all again in future in another episode of HPR. -------------------- References https://id3.org/Introduction https://www.xiph.org/ https://wiki.xiph.org/VorbisComment -------------------- Provide feedback on this episode.

  • August 4 · length unknown

    HPR4697: Correcting the Dates of Files

    This show has been flagged as Clean by the host. I recently had an experience where UNIX tools proved very useful. A relative had an old mobile phone running Android that stopped connecting to the carrier's network and bought a new one to replace it. I took on the job of trying to copy their files (consisting of just photos and videos) off of the old phone. Google's software was desperate to convince me to upload everything to the cloud, but I wasn't interested. It offered the option of copying the files over to an SD card, but failed on repeated attempts to do that. The option I tried next was to transfer them to another device via Bluetooth—that one did actually work, although it was slow and would only handle sending about 100 files at a time. They came over to my laptop OK, but the problem with that method was that all of the file times were set to the time when they were transferred. I'm not super familiar with how mobile apps manage metadata, but would presume that they look to file times for organizing photos by date. Fortunately, the names of each of the files included the date and time they were created. I recognized that I could write a bit of shell script to parse the filenames and set the file times accordingly. While there were over 800 files, the good news is that there were only three different categories of filenames, so the logic to extract the information needed was relatively simple. Each file had eight numerical digits representing the date and six digits representing the time. It would definitely be an option to come up with a more sophisticated parser that could handle a wide variety of filenames, but I went the lazy way and just handled those three cases. Another nice aspect was that none of the filenames contained spaces, which allowed me to be a bit less careful when using them in command lines. I didn't need to worry about time zones because my laptop was set to the same time zone as the phone—also, if a time was off a by a few hours it wouldn't make a practical difference. Examples of the three different types of filenames I had to deal with, labeled with the relevant values: YYYY=year, MM=month, DD=day, hh=hour, mm=minute, and SS=second. 00001IMG_00001_BURST20250525140124.jpg YYYYMMDDhhmmSS IMG_20220223_124023.jpg VID_20221017_095024.mp4 YYYYMMDD hhmmSS 20191224_195939.jpg 20161021_122620-1.jpg 20191130_134317_Burst01.jpg 20200129_223612_010.jpg YYYYMMDD hhmmSS I considered awk as an option (see Whiskeyjack's comment on HPR episode 4657 ), but realized it has no built-in way to change file times, so I set it aside. Don't worry, I will come back to that later. My approach was to use an if-then shell construct to choose how to treat the three categories of filenames. For the if condition, I fed the filename into the grep -q command with an appropriate regular expression to test whether it matches. The -q option to grep causes it not to output anything—it returns a zero exit status if there's a match and a status greater than zero if there isn't. Then, there is an elif statement with another grep -q test for the second category of filenames. Finally, an else statement is followed by the command to run for all other filenames. The whole thing is wrapped in a for loop that runs over all the files in the current directory. The touch command , when used with the -t option, can be given a string consisting of the year, month, day, hour, minute, and second. These are all numerals that are run together, except that a period sits between the minute and second. So we need a way to extract these numbers and to insert the period. That's where the cut utility comes in. It can be given a set of characters to select, and I specified a different set representing the appropriate ones depending on which category a filename fit into. To insert the period, I used sed to replace the last two characters with a period followed by those characters. The first script was to test out that I was getting the correct results. for fn in * do if echo "$fn" | grep -q BURST then printf "$fn " echo $fn | cut -c '21-34' | sed 's/..$/.&/' elif echo "$fn" | grep -q -E '^(IMG_|VID_)' then printf "$fn " echo $fn | cut -c '5-12,14-19' | sed 's/..$/.&/' else printf "$fn " echo $fn | cut -c '1-8,10-15' | sed 's/..$/.&/' fi done This one actually sets the file times. The -c option to touch prevents it from creating a file if one with that name doesn't already exist. for fn in * do if echo "$fn" | grep -q BURST then touch -c -t "$(echo $fn | cut -c '21-34' | sed 's/..$/.&/')" "$fn" elif echo "$fn" | grep -q -E '^(IMG_|VID_)' then touch -c -t "$(echo $fn | cut -c '5-12,14-19' | sed 's/..$/.&/')" "$fn" else touch -c -t "$(echo $fn | cut -c '1-8,10-15' | sed 's/..$/.&/')" "$fn" fi done The script ran over all the files in less than 15 seconds and correctly set the file time on each. Job done, right? Well, after I did this, it struck me that there was room for improvement. The script would probably run more quickly if I used a case construct instead of an if construct that called grep multiple times. While the pattern-matching notation used with case is not as flexible and can handle fewer situations than the regular expression syntax available with grep , in this case (see what I did there?) it is sufficient. Testing it out, using case reduced the running time by 45%. Replacing if with case —the commands to be executed for each category of filename can remain exactly the same. for fn in * do case "$fn" in *BURST*) printf "$fn " echo $fn | cut -c '21-34' | sed 's/..$/.&/' ;; IMG_*|VID_*) printf "$fn " echo $fn | cut -c '5-12,14-19' | sed 's/..$/.&/' ;; *) printf "$fn " echo $fn | cut -c '1-8,10-15' | sed 's/..$/.&/' esac done for fn in * do case "$fn" in *BURST*) touch -c -t "$(echo $fn | cut -c '21-34' | sed 's/..$/.&/')" "$fn" ;; IMG_*|VID_*) touch -c -t "$(echo $fn | cut -c '5-12,14-19' | sed 's/..$/.&/')" "$fn" ;; *) touch -c -t "$(echo $fn | cut -c '1-8,10-15' | sed 's/..$/.&/')" "$fn" esac done I couldn't completely put awk out of my mind, though, and I eventually came up with an awk script for the same purpose. This is far faster, probably because everything can be done within awk except actually modifying the file times, which is possible using the system() function to call touch . I was able to knock 90% off the running time, which for 800 files isn't a big deal but might make a difference if you have hundreds of thousands of files. The awk counterparts to both scripts above. Unlike those, ls is used to feed it with the list of filenames. We have the full power of extended regular expressions available to use for matching against the filenames. The next statement causes awk to skip any remaining pattern-action pairs and go to the next line of input. ls | awk '/BURST/ { print $0, substr($0, 21, 12) "." substr($0, 33, 2) next } /^(IMG_|VID_)/ { print $0, substr($0, 5, 8) substr($0, 14, 4) "." substr($0, 18, 2) next } { print $0, substr($0, 1, 8) substr($0, 10, 4) "." substr($0, 14, 2) }' ls | awk '/BURST/ { system("touch -c -t " substr($0, 21, 12) "." substr($0, 33, 2) " " $0) next } /^(IMG_|VID_)/ { system("touch -c -t " substr($0, 5, 8) substr($0, 14, 4) "." \ substr($0, 18, 2) " " $0) next } { system("touch -c -t " substr($0, 1, 8) substr($0, 10, 4) "." \ substr($0, 14, 2) " " $0) }' A further optimization that came to me later was to not call system() from within awk , but to instead just have awk print out a set of command lines. These can then be piped to sh to actually be executed. This cut the running time down by 95% compared to my original script. The fastest version I was able to come up with. If you run it without the | sh on the end, you can check that it's outputting the right information before actually modifying anything. The backslash on the end of a couple lines causes the subsequent line to be treated as a continuation of the existing line. Normally I would just keep everything on one line even if it runs longer than 80 columns, but for display purposes this looks nicer. ls | awk '/BURST/ { print "touch -c -t " substr($0, 21, 12) "." substr($0, 33, 2) " " $0 next } /^(IMG_|VID_)/ { print "touch -c -t " substr($0, 5, 8) substr($0, 14, 4) "." \ substr($0, 18, 2) " " $0 next } { print "touch -c -t " substr($0, 1, 8) substr($0, 10, 4) "." \ substr($0, 14, 2) " " $0 }' | sh It is probably true that this could have been carried out just as easily on Windows using Microsoft's PowerShell. I'm not very familiar with it, but would imagine (or hope) that it includes commands for managing these basic things like text manipulation and modifying file times. If you are stuck in an environment where you don't have a UNIX-like system available, investigate how to accomplish a task with the tools you do have. While I had the necessary information in the filenames to use, that might not be the case in all situations. You could look for other sources of dates—most digital cameras will add EXIF tags to a JPEG file giving the date and time it was created. (Hopefully, the clock in the camera will be set accurately.) While there is no standard UNIX utility to read those tags, free and open source software tools are widely available for that purpose. I found one called exiftags that included the utility exiftime , which specifically outputs EXIF data relating to time. The output format was a little trickier to handle, but awk was able to manage it with a little coaxing. Example of output produced by exiftime . Note that the first line with the filename is only printed if more than one filename is given as an argument. Also, for amusing-sign.jpg , apparently I edited that photo after taking it and the editing software updated the "created" tag but left the others intact. Not all images will necessarily have created, generated, and digitized tags; we will just take whichever ones exist. I redirected standard error to /dev/null to get rid of error messages for files that don't have EXIF tags; we'll handle those below. $ exiftime *.jpg 2>/dev/null 20260508_154743.jpg: Image Created: 2026:05:08 15:47:43 Image Generated: 2026:05:08 15:47:43 Image Digitized: 2026:05:08 15:47:43 20260508_155044.jpg: Image Created: 2026:05:08 15:50:44 Image Generated: 2026:05:08 15:50:44 Image Digitized: 2026:05:08 15:50:44 3704a78e771c2a25a894ef2f0b5a2a629f1eba80.jpg: amusing-sign.jpg: Image Created: 2017:01:24 23:14:04 Image Generated: 2017:01:24 21:18:07 Image Digitized: 2017:01:24 21:18:07 dscf3011.jpg: Image Created: 2015:01:01 00:02:19 Image Generated: 2015:01:01 00:02:19 Image Digitized: 2015:01:01 00:02:19 window-view.jpg: $ We can take advantage of the fact that different records are separated by a blank line. In awk , when RS is set to a null string and FS is set to a newline character, each set of non-blank lines is treated as a record and each line within those sets is treated as a field. One or more blank lines separate each record. For the output of exiftime , this means that $1 will contain the filename and $2 will contain the first line after the filename. For those files without an EXIF date tag, $2 will be a null string, which is treated by awk as FALSE, so the pattern will not match, the action will not be taken, and nothing will be printed. If a file has multiple tags, I will just use the first one reported by exiftime (contained in $2 ). The sub() function call removes the colon that exiftime prints after the filename, and the gsub() function call removes all non-numeric characters from the date and time in the tag. (After a comma within a print statement, a backslash is not necessary to continue a line.) Also, this time I bothered to print quotation marks around the filename in case it contains spaces. $ exiftime *.jpg 2>/dev/null | awk 'BEGIN { FS = "\n" ; RS = "" } $2 { sub(":$", "", $1) gsub("[^0-9]", "", $2) print "touch -c -t", substr($2, 1, 12) "." substr($2, 13, 2), "\"" $1 "\"" }' touch -c -t 202605081547.43 "20260508_154743.jpg" touch -c -t 202605081550.44 "20260508_155044.jpg" touch -c -t 201701242314.04 "amusing-sign.jpg" touch -c -t 201501010002.19 "dscf3011.jpg" $ I would imagine that there's some photo management program out there that I could have used to accomplish this. But then I would have had to locate it, verify that it wasn't some malware-loaded garbage, download, and install it. And chances are it would want to take over all the photos on my laptop. Instead, with standard UNIX tools and shell capabilities like if , case , process substitution, and pipelines, I was able to complete the task without having to install anything. The techniques I described can be used in different circumstances and with the output of different utilities. My intention was not just to explain how to solve this specific problem, but to hopefully teach you some things that you can apply in many situations. Perhaps if you use them to tackle a challenge of your own, you'll record an episode for HPR to share what you know. Provide feedback on this episode.

  • August 3 · length unknown

    HPR4696: HPR Community News for July 2026

    This show has been flagged as Explicit by the host. New hosts There were no new hosts this month. Last Month's Shows Id Day Date Title Host 4673 Wed 2026-07-01 First contact conversation Archer72 4674 Thu 2026-07-02 Audiobooks Ahuka 4675 Fri 2026-07-03 Yard Inflatables operat0r 4676 Mon 2026-07-06 HPR Community News for June 2026 HPR Volunteers 4677 Tue 2026-07-07 UNIX Curio #10 - Checksums and Hashes Vance 4678 Wed 2026-07-08 High Resolution Elapsed Time in Shell Scripts Whiskeyjack 4679 Thu 2026-07-09 HPR Beer Garden 15 - Double IPA Kevie 4680 Fri 2026-07-10 Robert A. Heinlein: The Future History, Part 2 Ahuka 4681 Mon 2026-07-13 My Disabilities Antoine 4682 Tue 2026-07-14 Behind the Keyboard: A Cybersecurity Operator’s Real-World Workflow operat0r 4683 Wed 2026-07-15 Recording the hallway track Ken Fallon 4684 Thu 2026-07-16 Sim Racing on the cheap! operat0r 4685 Fri 2026-07-17 Listening to SSB stations in the early 1980s Lennart Benschop 4686 Mon 2026-07-20 Debugging Security Cameras: Firmware Updates, Python Scripts and Windows Workarounds operat0r 4687 Tue 2026-07-21 UNIX Curio #11 - Merging Files Vance 4688 Wed 2026-07-22 Downloading Podcasts with a Shell Script Whiskeyjack 4689 Thu 2026-07-23 Cheap Yellow Display Project Part 8: Writing the code Trey 4690 Fri 2026-07-24 Playing Civilization V, Part 14 Ahuka 4691 Mon 2026-07-27 Viva la Coda Lee 4692 Tue 2026-07-28 Noise Music Tutorial 2: Using Audacity to Make Noise TheDUDE 4693 Wed 2026-07-29 Amateur Radio Field Days Archer72 4694 Thu 2026-07-30 HPR Beer Garden 16 - Belgian Blonde Kevie 4695 Fri 2026-07-31 Try not to buy a phone operat0r Comments this month Past shows hpr4644 (2026-05-21) "Response to comments on HPR4424: Newsboat..." by Archer72. Archer72 said: "Ken on Community Show HPR4676" (2026-07-06 13:48:39) Ken Fallon said: "hpr3962 :: It's your data" (2026-07-06 15:07:47) hpr4669 (2026-06-25) "HPR Beer Garden 14 - Super Strong Lager" by Kevie. The_Dud3 said: "Favorite Malt Liquores/Super Strong Lagers" (2026-07-22 02:07:59) hpr4672 (2026-06-30) "Hey Mum, I'm on Spotify ! " by Ken Fallon. Archer72 said: "Another great show!" (2026-07-08 09:46:44) This month's shows hpr4674 (2026-07-02) "Audiobooks" by Ahuka. The Librarian said: "Ook ?" (2026-07-02 10:50:38) hpr4677 (2026-07-07) "UNIX Curio #10 - Checksums and Hashes" by Vance. xmanmonk said: "Another great show" (2026-07-07 21:17:41) candycanearter07 said: "cool show :D" (2026-07-08 11:32:04) Vance said: "Thanks, and systemd as a future topic" (2026-07-09 01:50:23) Vance said: "Sorry, xmanmonk" (2026-07-12 03:20:02) hpr4678 (2026-07-08) "High Resolution Elapsed Time in Shell Scripts" by Whiskeyjack. candycanearter07 said: "cool ep" (2026-07-09 14:38:32) Whiskeyjack said: "Reply to candycanearter07 on HPR4678" (2026-07-09 22:48:47) hpr4681 (2026-07-13) "My Disabilities" by Antoine. Archer72 said: "Reading" (2026-07-22 13:43:46) hpr4684 (2026-07-16) "Sim Racing on the cheap!" by operat0r. Jim DeVore said: "Great episode!" (2026-07-28 03:43:23) hpr4685 (2026-07-17) "Listening to SSB stations in the early 1980s" by Lennart Benschop. Lucinda said: "Thank you" (2026-07-21 10:53:42) hpr4688 (2026-07-22) "Downloading Podcasts with a Shell Script" by Whiskeyjack. candycanearter07 said: "cool solution" (2026-07-22 23:14:22) Whiskeyjack said: "Response to candycanearter07 in HPR4688" (2026-07-23 19:14:55) Mailing List discussions Policy decisions surrounding HPR are taken by the community as a whole. This discussion takes place on the Mailing List which is open to all HPR listeners and contributors. The discussions are open and available on the HPR server under Mailman. The threaded discussions this month can be found here: https://lists.hackerpublicradio.com/pipermail/hpr/2026-July/thread.html Events Calendar With the kind permission of LWN.net we are linking to The LWN.net Community Calendar. Quoting the site: This is the LWN.net community event calendar, where we track events of interest to people using and developing Linux and free software. Clicking on individual events will take you to the appropriate web page. Provide feedback on this episode.

Showing 1–20 of 21 episodes