Lua OS Library

We’re going to go over the default OS library included in Lua. This library is very useful, but is also platform specific. What works on one OS may not work on another.

Once you start using an OS library, you run the risk of your code losing portability. If you use a clock or the time for a random number seed, it’s not going to impact your program (except possibly cryptographic functions), but how do you get a list of files in a directory? How do you account for differences between versions? Aside from extra handling code to re-abstract the OS functions, you really can’t.

os.execute( [command] )

This is one of the most well known types of commands in any programming language which has an OS library. Almost every language includes a way to tell the local shell to do something from a program. os.execute( [command] ) runs a given command and returns its run status. This will be either a boolean for true or false if it launched to the shell and terminated successfully or with an error respectively, or nil otherwise (some system issue or similar prevents it from running at all).

You should use local system handling to output the results somewhere so you can open them as a file to read back in. This can be treated as a one way operation with a variable to tell you if it dispatched correctly or not.

If we do something like:

#!/usr/bin/lua5.1

local results = os.execute( "ls /tmp" )

print( "------" )
print( results )

We do get the results of ls /tmp dumped to the command prompt, but we really can’t use them. We can theoretically use a pipe out to a file which we can then read. Most builds of Lua will include another tool io.popen which can be used instead. If you have to use a system specific function, there’s usually a better way to accomplish what you want to do.

io.popen( [process] [, [mode]] )

io.popen stands for “process open” or “program open”. We open a process and can set a mode like we can with a normal file. The mode defaults to “r” for read only. It can also be set to “w” for write.

Here’s an example of io.popen in action:

#!/usr/bin/lua5.1

local results = io.popen( "ls /tmp" )

for v in results:lines() do
	print( v )
end

results:close()

This gets us:

./ostest.lua 
CEYitlJJC4OPp1hFCRuFHG4j16jyZDbGCv5wgC8I5co=
gimp
hsperfdata_root
lu240860kldgtz.tmp
OSL_PIPE_1000_SingleOfficeIPC_eb375abbe7e889ed8f9c4c4cbe325
qipc_sharedmemory_CEYitlJJCOPphFCRuFHGjjyZDbGCvwgCIco1a2ab64991428580c3ee730af7d20cf8c47e333c
qipc_sharedmemory_qtsingleapplicationbfde75a5bf91e5179df8ee7ad4556d71fef8ca2ca6aa
qipc_systemsem_CEYitlJJCOPphFCRuFHGjjyZDbGCvwgCIco1a2ab64991428580c3ee730af7d20cf8c47e333c
qtsingleapplication-9a03-3e8
qtsingleapplication-9a03-3e8-lockfile
Screenshot_2019-11-30_11-19-16.png
sndio
ssh-3b93JAb20hcs
stardict
systemd-private-e212241de75e4076bfbf4e092c6224aa-colord.service-ntbSQp
systemd-private-e212241de75e4076bfbf4e092c6224aa-iio-sensor-proxy.service-vPqXm6
systemd-private-e212241de75e4076bfbf4e092c6224aa-ModemManager.service-84gmiw
systemd-private-e212241de75e4076bfbf4e092c6224aa-systemd-logind.service-3ZMStT
systemd-private-e212241de75e4076bfbf4e092c6224aa-systemd-timesyncd.service-m6nXLM
systemd-private-e212241de75e4076bfbf4e092c6224aa-upower.service-zUbKQ8

This code is no longer portable however as it is meaningless on Windows and will probably fail on many other OSes depending on the filesystem setup.

os.exit( [[code]] )

This tells our program to exit with an optional code. The code defaults to success. This is extremely useful for debugging complicated processes. You can run a bunch of code, dump a state and exit before a large amount of processing happens if you aren’t debugging that part of the program. The codes can also be used to tell you why a program exited. This can be useful for testing loops or conditional handling.

OS Clock Functions

os.clock()

This gets back an approximation of the number of seconds which have elapsed since execution. This function is useful for seeding a random number generator or similar, but is not necessarily going to be entirely portable. Keep in mind, it returns an approximation.

os.date( [format [, [time] ] ] )

This prints the date. If the format parameter is present, it prints based on the local implementation of strftime in C. If the time is present, it works based off of a time supplied (which should follow the format of os.time([[table]])). The format is going to be similar to something like printf.

Formats

FormatDescription
%aWeekday abbreviation
%AWeekday name
%bMonth abbreviation
%BMonth name
%cFull time representation (default)
%dDay of the month
%HHour in 24 hour time
%IHour in 12 hour time
%jDay of the year
%mMonth (01-12)
%MMinute
%pAM or PM
%SSecond
%UWeek number (starting from first Sunday of the year)
%wWeekday as a decimal starting from Sunday (as 0)
%WWeek number (starting from first Monday of the year)
%xDate representation (01/23/45)
%XTime representation (01:23:45)
%yLast 2 digits of the year
%YFull year
%ZTimezone
os.difftime( t1, t2 )

This returns the difference in seconds between t1 and t2. This uses a time format from os.time().

os.time( [[time table]] )

This returns the current time as a representation on your current system. If a time table is passed, it can be a date or a datetime which requires: year, month, day, and can take: hour, min, sec, and isdst. If you plan to work with time and don’t want to use an outside library, make sure to convert times properly.

Files and Folders

You can work with files and folders in a very generic way with Lua’s OS library.

os.remove( [target] )

Have the OS remove target. If this is a directory, it must be empty. It returns true on success or nil and an error on failure.

os.rename( [orig], [new] )

Rename a file from orig to new. Returns true on success or nil and an error on failure.

os.tmpname()

Gives an OS specific filename for a temp file. This shouldn’t be used for anything too important and this function doesn’t actually help you open the file.

Locales and Local Environment

os.getenv( [var] )

Get the local variable var. Returns nil if it doesn’t exist.

os.setlocale( [locale] [, [cat]] )

Set the local or a category: cat to the specified locale. If locale is empty (“”), then set it to the system specific locale. If locale is nil, return the current locale.

Using the OS Library

The OS library is fine to use for certain types of tasks, but keep in mind you run the risk of sacrificing portability when you use it. Some functions like os.exit() and some of the time and file functions are relatively safe, but as soon as you get the OS involved you need to go a bit further for portability. This library has its place, but it complicate debugging your code depending on the build and implementation of Lua. Use it as sparingly as possible.