317 episoder
- 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. - 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. - This show has been flagged as Clean by the host.
IDEAS:
Using a cheap phone plan with SMS for authentication.
Mighty Text as a free SMS solution.
Google VoIP number for shared accounts.
Issues with SMS verification blocking VoIP numbers.
Avoiding carrier-specific number blocks.
Multiple SIM cards for cost-effective SMS.
Rooting a phone to manage apps.
Security concerns with third-party apps.
Limited data usage for minimal phone plans.
Challenges with app compatibility on rooted devices.
Short-term phone solutions for SMS needs.
Shared Google accounts for streamlined access.
Avoiding premium SMS services like $15/month plans.
Using Wi-Fi for data instead of cellular plans.
Importance of SMS for MFA (multi-factor authentication).
Transitioning from old phones to new setups.
Balancing convenience and cost in phone plans.
Reliance on SMS for banking and insurance access.
Difficulty finding non-blocked SMS verification options.
Preference for minimal, low-cost phone solutions.
RECOMMENDATIONS:
Use a shared Google account for SMS access.
Opt for a cheap phone plan with unlimited texting.
Try Mighty Text as a free SMS alternative.
Avoid premium SMS services with high fees.
Use Wi-Fi instead of cellular data for minimal plans.
Choose carrier numbers over VoIP for critical services.
Root a device to manage app settings.
Test SMS compatibility with banks and providers.
Consider multiple SIM cards for redundancy.
Prioritize SMS for MFA over other verification methods.
Monitor app updates for compatibility with rooted devices.
Select phones with flexible data plans.
Use downloaded content instead of streaming.
Check for SMS blockages with new services.
Explore low-cost phone options for minimal use.
Maintain backup SMS methods for emergencies.
Simplify phone setups to reduce costs.
Verify SMS support before switching providers.
Combine Wi-Fi and SMS for reliable connectivity.
Share accounts to streamline digital access.
Provide feedback on this episode. - This show has been flagged as Clean by the host.
Dave and Kevie are back with another HPR Beer Garden and this time they turn their attention to Belgian Blonde Ales. Kevie samples
Leffe Blonde
, whilst Dave opts for
La Chouffe
.
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 3 beer styles to be reviewed:
DDH IPA
Amber Ale
Lager
Provide feedback on this episode. - This show has been flagged as Clean by the host.
Hi, this is Archer72 for another episode of Hacker Public Radio.
In this episode, the ARRL Field Days was in the past month, so I thought this would be a good time to highlight events in the US as well as around the world.
Field Day (amateur radio : edited on 4 June 2026, at 13:51)
Experience the power of ham radio at 2025 ARRL Field Day Harrison County Amateur Radio Club Jun 12, 2025
Updated Jun 17, 2025
Amateur Radio Club to host annual field day By Keith Clifford Harrison County Amateur Radio Club Jun 15, 2026
Harrison County Amateur Radio Club Field Day Jun 22, 2026
Preceding collage used with permission by Keith Clifford of the Harrison County Amateur Radio Club (K4HSN)
Provide feedback on this episode.
Flere Nyheder podcasts
Trendige Nyheder podcasts
Om 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.
Podcast-webstedLyt til Hacker Public Radio, Børsen Morgenbriefing og mange andre podcasts fra hele verden med radio.dk-appen
Hent den gratis radio.dk-app
- Bogmærke stationer og podcasts
- Stream via Wi-Fi eller Bluetooth
- Understøtter Carplay & Android Auto
- Mange andre app-funktioner
Hent den gratis radio.dk-app
- Bogmærke stationer og podcasts
- Stream via Wi-Fi eller Bluetooth
- Understøtter Carplay & Android Auto
- Mange andre app-funktioner

Hacker Public Radio
Scan koden,
download appen,
begynd at lytte.
download appen,
begynd at lytte.
