- MCP server with stdio transport for local use - Search episodes, transcripts, hosts, and series - 4,511 episodes with metadata and transcripts - Data loader with in-memory JSON storage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
243 lines
19 KiB
Plaintext
243 lines
19 KiB
Plaintext
Episode: 3551
|
|
Title: HPR3551: Bash snippet - some possibly helpful hints
|
|
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr3551/hpr3551.mp3
|
|
Transcribed: 2025-10-25 01:18:53
|
|
|
|
---
|
|
|
|
This is Hacker Public Radio Episode 3551 for Monday the 14th of March 2022.
|
|
Today's show is entitled, Bash snippet, some possibly helpful hint and is part of the series
|
|
Bash scripting.
|
|
It is hosted by Dave Morris and is about 25 minutes long and carries an explicit flag.
|
|
The server is using the file, map file and then environment variables.
|
|
Hello everybody, this is Dave Morris for Hacker Public Radio.
|
|
I'm going to do a show today within the series Bash scripting.
|
|
This is one I've called some possibly helpful hints, just a bunch of things that I've been
|
|
doing in scripts lately and I thought I'd share just in case it reviews to anybody else.
|
|
So I write a moderate number of Bash scripts these days.
|
|
I know the Bash isn't a programming language but it's pretty powerful in what it can do
|
|
all by itself actually and with other tools.
|
|
It's like said an organ that type of thing, it's really, really capable.
|
|
I've actually been writing the sorts of command script I suppose you'd call them for a long
|
|
time since the 1970s on a whole variety of hardware and operating systems.
|
|
Maybe we should talk about them someday.
|
|
I remember them that is, Bash is my favourite because it's pretty flexible and also Linux
|
|
itself, it's very flexible.
|
|
Anyway, forget the history for now.
|
|
I just want to talk about three things I tend to do in Bash scripts that assist some
|
|
of the things I need to undertake some of the tasks I find I need to get a solution to.
|
|
So the first one is to generate Bash variables from a text file.
|
|
So you've got a text file which has got stuff like a keyword and a string or a number
|
|
or something and you want to turn that into Bash variables.
|
|
Second one is to fill Bash arrays with data from a file or a program or that type of thing.
|
|
And the third one is to use environment variables or just general shell variables within the
|
|
environment of the script to control the Bash script execution.
|
|
So I'll expand on these.
|
|
So first of all, generating a Bash variables.
|
|
There's a Bash command, eval, eval, that can be used to evaluate the string as a command
|
|
or series of commands if you want to put new lines or semicolon to between them.
|
|
And the evaluation takes place in the current shell.
|
|
So anything returned and in my particular example I'm using Bash variables is available
|
|
to the current script.
|
|
So this type of thing is available in a lot of programming languages, scripting languages
|
|
where you might want to invoke a command within a script and the command is something
|
|
you have generated in real time, I guess you'd say.
|
|
If you were to set variables in a sub-shell which in fact is something like issuing some
|
|
commands in parentheses or when you invoke a script or a function or something, then
|
|
the variables are local to the sub-shell and they disappear when that particular process
|
|
finishes.
|
|
So the eval command, we haven't looked at it in detail but I've mentioned it in other
|
|
contexts along this series.
|
|
The eval command takes a list of arguments of any number I think which are just concatenated
|
|
into a string and that string is taken to be the command to be evaluated.
|
|
I should say that the eval command is seen as potentially dangerous then it will execute
|
|
any command it's given.
|
|
So if by some means rather you've ended up with a command string that says RM tilde slash
|
|
star or something then it could go and delete all your files.
|
|
How would that come about?
|
|
Well, you might have made the mistake of allowing people to feed commands to the script
|
|
that's doing it where that would be one of them.
|
|
So you need to bear that in mind whenever you're doing this type of thing.
|
|
Don't write a script that just executes whatever it's given to it.
|
|
It needs to be vetted or you need to know exactly where that commands are come from before
|
|
you invoke them.
|
|
Now one of the particular cases where I use eval is for setting variables from a text
|
|
file as I mentioned.
|
|
I've got a file which is generated from the HPR show upload process and I want to grab
|
|
the title of the show, the summary in relating to show and the host name of the person submitting.
|
|
So I can generate an index file for any supplementary files which have come in with the show.
|
|
I don't need to do this all the time but there are occasions when people send in example
|
|
scripts or pictures and what that sort of thing.
|
|
So I just wanted to be able to get these things and turn them into a bit of text in an HTML
|
|
file.
|
|
So in my script that does this, I won't go into details about it because it's quite complex
|
|
but it uses eval with a, actually use a quoted string which in which is a command substitution
|
|
which invokes said and said is looking for the keywords that the layer of this particular
|
|
file, the keywords begin in column one and they are title or summary or host underscore name.
|
|
So any line that matches one of those is picked up by said and is manipulated such that
|
|
the end result is that keyword, which is all one word, an equal sign and then in single quotes,
|
|
the string that follows it.
|
|
So I show an example of how the said command would actually work all by itself and there's
|
|
a reference to a very book called raw file here which is where I would have put the path
|
|
to the file in the script.
|
|
So just take that as a given and it's reporting back the host name, this is one of my shows
|
|
is Dave Morris and blah, blah, blah, title and summary of them.
|
|
So that's pretty basic said stuff and if you listen to my said series you should be able
|
|
to decode that pretty easily and see what it's doing.
|
|
So what Eval does is it runs the command substitution with the said command in it and the result
|
|
of all that is a string which is actually separated by new lines but the way that command
|
|
substitution works is that the new lines are turn to spaces.
|
|
So these will be fed to Eval and Eval's quite happy to receive three variable definitions
|
|
on the same line separated by a space, each one or space is.
|
|
So what that does is to set a variable called host underscore name to one string, one
|
|
called title to another string, one called summary to a third string and these are then
|
|
available in the script that's called Eval.
|
|
Now the way I've done this is not foolproof as I say in the notes because I'm wrapping
|
|
the text in single quotes, if there was a single quote within one of these strings then
|
|
it would break cause I haven't taken any particular action to avoid such a thing but it's
|
|
working for now and I'm happy with that but I do need to work a little bit more on it
|
|
to make it less fragile.
|
|
Okay second one is filling bash array.
|
|
So this is another thing I need to do in the context of writing scripts for HPR, janitorial
|
|
things.
|
|
I've got an index array and I want there to be sorted file names in that array and then
|
|
I want to be able to process the contents of that array and I'm doing it because I've
|
|
got a show that's come in which includes bunch of pictures so I want to be able to do
|
|
some automation with the way I handle the pictures.
|
|
Well how do I find the pictures?
|
|
Well first of all there's a path which points to the directory in question which is called
|
|
shoulder, all in capitals, SHOWWDIR.
|
|
I use the find command against this path with a max depth option of one that means don't
|
|
go down to lower directories and then it uses a regular expression thing.
|
|
In find you have to say what type of regular expression you're using there's a hyphen
|
|
reject type eGrep which I use so that causes the eGrep engine to be used in the regular
|
|
expression.
|
|
And the regular expression simply says dot asterisk backslash dot, yes so it's looking for
|
|
any old text and including a backslash space, a backslash dot I should say, followed
|
|
by either JPEG or PNG in upper or lower case.
|
|
So that's how it finds pictures if you send in a picture that has some other form
|
|
it won't work.
|
|
Anyway it'll do that, does that quite well but that hasn't solved the problem yet but
|
|
it's a component.
|
|
So I've got an example here where you could define the array so I've got declare hyphen
|
|
and a PIXPIX for pictures then I do PIX equals open parenthesis and then a command substitution
|
|
with the find in it that I just mentioned it's all listed out in the notes here.
|
|
The find is actually followed by a vertical bar to pipeline and it sends its output to
|
|
sort.
|
|
If you did that then the find and the thought will return a number of new lines separated
|
|
lines containing filenames you know in alphabetical order but again as I said before the command
|
|
substitution replaces new lines by spaces so what bash will see in this in the parenthesized
|
|
list is a bunch of words or strings which are then fed into the array and that's great
|
|
that works but it's relying on the fact that the file name delimitar is a space but
|
|
it's permitted to have spaces and filenames it's not a good thing to do but it happens.
|
|
So how would you make this better to avoid that one?
|
|
I use the command map file I talked about map file in episode 2739 and you can also find
|
|
information about it by typing help map file in a terminal so there's a little snippet here which
|
|
is a declaration of the array again then we use map file then hyphen t which means remove the
|
|
default delimitar the default delimitar is a new line then the name of the array picks
|
|
then less than and I've split this into two lines with the backslash new line in it then we've
|
|
got a process substitution which hopefully you'll remember from other shows in this series which
|
|
is a less than sign immediately followed by an open parenthesis then you would put commands in
|
|
there and close the parenthesis and the commands are defined as before exactly the same find
|
|
and a sort in a pipeline you could have other delimitar here we'll talk about that in a second
|
|
but the map file chops up what it sees on its standard input which is coming from this process
|
|
substitution thing and it puts them one at a time into array elements if the array exists it will
|
|
just overwrite it so that that's great you could change the other delimitar as I said and there are
|
|
providing there are no files with new lines in them then you're good because a new line is valid
|
|
in a file name it's a it's a thing I have never used not really encountered much but it's possible
|
|
to do it I've done it by mistake I guess long ago in the next days well I didn't know what I was
|
|
doing what I said here is that to be 100% safe and be protected from potential new lines in file name
|
|
you can make find produces output using the hyphen print zero option which prints out every line
|
|
or if you file in the case where it's reporting files with a null character at the end of it
|
|
instead of a new line so map file can be told to use a null as the delimitar by simply giving it
|
|
hyphen D and then a null string so open quote close quote so here's an example which shows
|
|
the find with hyphen print zero the sort still works on that which is good I wasn't sure
|
|
it would but it does and it sorts them correctly and you are then not prone to any any of the potential
|
|
problems of funny characters and new lines and spaces or whatever I have to tell you
|
|
coming to you that I discovered this information and messed around with it and tested it while
|
|
preparing for this show so I'm going to go and update my script to use it once I've finished
|
|
so the last hint or tip or snippet or whatever you want to call it is talking about turning
|
|
debugging on in a script so I tend to use debugging statements in the script which get a little
|
|
bit more complex than than others and I tend to write simple function which I've listed here
|
|
which I call underscore debug in capitals for some reason I can't remember I did that the
|
|
underscore just sort of makes it stand out a little bit perfectly valid character is part of a
|
|
naming and can be the first character of the name so in there I test to see whether a global
|
|
variable debug is zero and if it is then just return so effectively do nothing but if the debug
|
|
is not zero then there's a loop which loops through the variable which is actually an array
|
|
dollar at dollar at is a list of all the arguments to to a script or to a function so it's going
|
|
to all the arguments that function and for each one it uses the print f command to print out
|
|
its contents with a new line on the end and a d greater than space in front of it so when you look
|
|
at it you can see well that's debug output the variable that I'm using to hold these these arguments
|
|
is msg so I use that as the argument to print f it's very simple and that works pretty well it does
|
|
pretty much what I want it to do so I what I just do I do is to plant a bunch of calls to this
|
|
function throughout my script whenever I want to check that things I have read or calculated or
|
|
whatever I want to check that they contain what I expect them to contain and you be surprised
|
|
the number of times they don't and that's what debugging is all about but the thing is how do you turn
|
|
debugging on and off you want something relatively simple but listed three possible ways you could
|
|
do this the first one is is really clunky you could edit the script to set the debug variable to
|
|
one when you want to turn debug on or zero when you don't but that means you got to keep editing
|
|
the script which is the pain second one is you could set the debug level through an external
|
|
variable which the script can see and the third one is to add option processing to the script
|
|
so you recall the script with a minus with a hyphen capital D perhaps to mean turn on debugging
|
|
and you would you would enable or disable it at that point I tend to use option three
|
|
the option processing thing when I'm already scanning for and and dealing with options in my script
|
|
but if I'm not doing that then I use choice two that is the external variable and that's
|
|
I'm going to explain now so bit preambo I use vim as my editor and in vim I use a plugin called
|
|
bash the port which I can set up boilerplate text within which is to be added to script or can
|
|
be given as a default framework for a new script and I've got various definitions and declarations
|
|
and comments and stuff that go in by default one of the lines that's particularly important is one
|
|
which defines the variable script in capitals equals and then I've got dollar open curly brace
|
|
zero hash hash asterisk slash close curly brace so that takes the default variable
|
|
dollar zero which contains the name of the script as it was invoked so if you put the full path name
|
|
and invoked the script from somewhere other than where the script lives then that will contain
|
|
the entire path if you're in the directory where it lives and you put dot slash script name
|
|
then it will just contain the dot slash and the script name whatever happens there
|
|
that expression trims off stuff from the front of that string the dollar zero string
|
|
and it specifies it's to keep doing that until it hits a slash and in other words it it will
|
|
do this repeatedly until it takes out everything up to the last slash so just leave the name of the
|
|
name of the script I did talk about this stuff way back in the early days of doing bash scripting
|
|
now I've started adding two lines relating to debugging the first one is to define a variable
|
|
called debug var or in capitals d-e-b-u-g-v-a-r set that to put this in in quotes dollar open curly
|
|
bracket script close curly bracket underscore debug so that means debug var will contain the name
|
|
of the script which had just chopped down to its last component well that's the base name isn't it
|
|
yeah if you use the base name command instead followed by underscore debug in capitals then the
|
|
next line is debug equals that's the variable that I want to use to control whether you see debug
|
|
output or not then in double quotes dollar open curly bracket exclamation mark debug var colon
|
|
hyphen zero close curly bracket close double quotes what that says is the variable debug var
|
|
with an exclamation mark on the front of it it is to is an indirection to the variable whose name
|
|
is in that variable so it's doing one level of indirection so it's using the contents
|
|
and it's saying whatever that variable contains it if it if it exists it does contain something use it
|
|
if it doesn't the colon hyphen business contain if you can't find it it doesn't exist then set debug
|
|
to zero what that means it's a little involved that but it's um once as I say it's a bit of boiler
|
|
plates I'm going to slap that in scripts by default and uh it's useful just to put it in
|
|
without really thinking about it anymore but what it achieves is it it allows the script to be called
|
|
with a variable definition before it on the same command line so if you had a script which is called
|
|
test script and you'd call this variable test script underscore capital debug and I'm in this
|
|
example I'm setting it to one then space dot slash test script folks test script and it will cause
|
|
the internal debug variable to be set to one which will switch on all the debug stuff variables set
|
|
on the command line are visible to scripts in fact variables set in the environment are visible
|
|
to to a script whether they be exported ones which I talked about a few episodes back or just
|
|
all new ones the one set on the command line only last while the script or indeed command is
|
|
executing you could set an exported variable so one example here export space test script underscore
|
|
debug equals one then on the next line dot slash test script but that variables can hang around after
|
|
the script is run and you'd need to go and un-set it to make it go away so if you want to turn
|
|
debugging off you would need to use the un-set command to delete that variable the thing that
|
|
think about the putting it on the same line mean is that if you just run test script without that
|
|
setting a variable preamble then it will run without debug so that's that's fine I definitely
|
|
don't like to do the export business so when I give these more complex names to my debug variables
|
|
that I've just been talking about test script underscore debug so there's less chance of them
|
|
affecting other scripts than the one I'm trying just currently debugging if I just use the name debug
|
|
then that might cause anything I run to go into debug mode that seems to be about ideas so I'm
|
|
using sort of namespaces to keep things separate so in conclusion these are just the three things
|
|
I found myself using in recent bash script which I hope might be useful to you if you have hints like
|
|
this which you could share please make an HBR show about them we're always in need of shows
|
|
I'm sure you know at the time of writing which is the 26th of February we are particularly in need
|
|
and there's a lot of empty slots stretching out into the into the near future so from the near future
|
|
forever okay then bye
|
|
you've been listening to Hecker Public Radio at HeckerPublicRadio.org
|
|
today's show was contributed by an HBR listener like yourself if you ever thought of recording a
|
|
podcast then click on our contribute link to find out how easy it really is hosting for HBR
|
|
is kindly provided by an honesthost.com the internet archive and our sync.net unless otherwise
|
|
stated today's show is released under a creative commons,
|
|
Attribution ShareLikeThoi.org license
|