Off-Topic > Off-Topic - Tiny Tux's Corner
[Solved] Asking for recomendations on the shell script formatting.
Rich:
Hi jazzbiker
--- Quote from: jazzbiker on July 19, 2023, 08:43:19 AM --- ... logs are declared as local ... but are used in main(): ...
--- End quote ---
The busybox ash shell includes local as one of its built-ins. Enter help in a terminal:
--- Code: ---tc@E310:~$ help
Built-in commands:
------------------
. : [ [[ alias bg break cd chdir command continue echo eval exec
exit export false fg getopts hash help history jobs kill let
local printf pwd read readonly return set shift source test times
trap true type ulimit umask unalias unset wait
tc@E310:~$
--- End code ---
Here is an example of local:
--- Code: ---#!/bin/sh
Var=5
TestLocal()
{
# This echos the global Var.
echo "2 Var=$Var"
# This overrides the global Var with an empty local Var.
local Var
echo "3 Var=$Var"
# This sets the local Var to 3.
Var=3
echo "4 Var=$Var"
}
echo "1 Var=$Var"
TestLocal
echo "5 Var=$Var"
--- End code ---
This is the result:
--- Code: ---tc@E310:~/split$ ./LocalDemo
1 Var=5
2 Var=5
3 Var=
4 Var=3
5 Var=5
tc@E310:~/split$
--- End code ---
jazzbiker:
--- Quote from: CardealRusso on July 19, 2023, 12:10:09 PM ---Currently, CoreScripts bash scripts are neither easy to read nor user friendly (though understandable).
--- End quote ---
Core scripts have one huge advantage - they work properly ) I don't want to propose repair what's working right. For TinyCore phenomenal stability is absolutely unique. Some features are accessible only in TinyCore.
And even if put the question - what I would like to rewrite in Core? Frankly speaking - nothing. Extending preferably be done in some new ways or new tools, but the Core is wonderful! Stability is easy to destroy but impossible to repair.
If talk about another languages, for example Lua, some things may be taken into consideration. For example I wrote the Lua version of the initial script. Here it is:
--- Code: ---#!/usr/bin/env lua
local TDir, TName = arg[1]:match("(.-)([^/]*)$")
------------------------------------------------
-- Auxillary function to run complex commands --
------------------------------------------------
local run = function(cmd)
assert(os.execute(table.concat(cmd)))
end
run{"depends-on ", TDir, ".do..", TName}
------------------------------
-- Gathering necessary data --
------------------------------
local jobs = tonumber(os.getenv("JOBS")) or 2
local map_dir = assert(io.popen("cd " .. TDir .. "./; pwd")):read()
-----------------------
-- Storing log names --
-----------------------
local log_names = {}
for i = 1, jobs do
log_names[#log_names + 1] = string.format("%s.%d.log", arg[1], i)
end
------------------------------------------
-- Creating and running complex command --
------------------------------------------
local cmd = {}
for i, name in ipairs(log_names) do
cmd[#cmd + 1] = string.format("redo -l %s -m %s %s & ", name, arg[1], arg[2])
end
cmd[#cmd + 1] = "wait"
run(cmd)
----------------------------------------------
-- Concatenation of partial logs in one log --
----------------------------------------------
local log_name = arg[1] .. ".log"
local flog = io.open(log_name, "w")
flog:write("return {\n")
for i, name in ipairs(log_names) do
flog:write(io.open(name):read("a"))
end
flog:write("}\n")
flog:close()
---------------------------------
-- Loading the processing code --
---------------------------------
log2map = assert(loadfile("log2map.lua"))
------------------------------------
-- Emulating MAP_DIR env variable --
------------------------------------
local getenv_orig = os.getenv
os.getenv = function(name)
if name == "MAP_DIR" then
return map_dir
end
return getenv_orig(name)
end
------------------------
-- Redirecting stdout --
------------------------
assert(io.output(arg[3]))
-----------------------
-- Processing itself --
-----------------------
log2map(log_name)
--- End code ---
As You can see it is slightly bigger ) Still for me such approach is more comfortable, because everything is clear and all aspects of code are accessible and changeable. No limitations of what can be done - absolutely everything. Which is wrong for shell. Some things are absolutely impossible to do with shell.
GNUser:
--- Quote from: jazzbiker on July 19, 2023, 03:17:43 PM ---Core scripts have one huge advantage - they work properly ) I don't want to propose repair what's working right. For TinyCore phenomenal stability is absolutely unique. Some features are accessible only in TinyCore.
--- End quote ---
Wow, well said! Some TCL scripts are not very pretty but they work perfectly and I wouldn't touch them.
I use my TCL-powered laptop and wireless router daily and my overall impression of TCL is that, by minimizing size and complexity, it is the most stable and easy-to-understand GNU/Linux distribution that exists.
P.S. My *nix journey was Debian -> Arch Linux -> OpenBSD -> Devuan -> TCL. I still manage a Devuan machine in my household (wife's laptop) but I, personally, am 100% TCL. Once you're used to TCL, the complexity and size of other distros is just not acceptable.
jazzbiker:
--- Quote from: Rich on July 19, 2023, 12:54:36 PM ---The busybox ash shell includes local as one of its built-ins. Enter help in a terminal:
--- End quote ---
Thanks for explanations and examples, Rich! It works as expected. But in GNUsers example it was looking strange and I was not sure whether it works in shell the same way as in another languages. But GNUser wrote that it is not POSIX feature and for better portability it must not be relied upon.
Best regards!
CardealRusso:
--- Quote from: jazzbiker on July 19, 2023, 03:17:43 PM ---Core scripts have one huge advantage - they work properly
--- End quote ---
I agree. Unfortunately it is sad to see that the latest commits on such scripts go back 10 or more years.
I'm not very familiar with Lua, but it's a surprisingly easy language. Unfortunately, the beginning is interesting but when the lua script ends it is noticeable that its syntax is no longer modern. The constant use of "ends" and other redundancies makes lua outdated.
In case you're curious, I started making a standalone version of tce-size in lua, as a demo. The LOC seems unnecessarily large, but keep in mind that there is no dependency. The script is also incomplete, but is partially working. You can test from https://www.jdoodle.com/execute-lua-online/ and inserting the package name in the argument.
--- Code: ---function GetRemoteContent(url)
local isGzipped = url:sub(-3) == ".gz"
local wgetCmd = string.format("wget -q -O- %s", url)
if isGzipped then
wgetCmd = string.format("%s | gunzip", wgetCmd)
end
local handle = io.popen(wgetCmd)
local content = handle:read("*a")
handle:close()
if content and #content > 0 then
return content
else
print(string.format("Failed to download content from '%s'.", url))
return nil
end
end
function getFileSize(sizelistContent, filename)
for line in sizelistContent:gmatch("[^\r\n]+") do
local file, size = line:match("(%S+)%s+(%d+)")
if file == filename then
return tonumber(size)
end
end
return 0
end
function FileExist(filename)
local path = "/etc/sysconfig/tcedir/optional/" .. filename
local file = io.open(path, "r")
if file then
file:close()
return true
else
return false
end
end
local app = arg[1]
if not app then
print("Specify extension in command line:")
print("Example: /usr/bin/tce-size firefox.tcz.")
return
end
if not app:match("%.tcz$") then
app = app .. ".tcz"
end
local sizelistURL = "http://tinycorelinux.net/14.x/x86_64/tcz/sizelist.gz"
local treeURL = string.format("http://tinycorelinux.net/14.x/x86_64/tcz/%s.tree", app)
local sizelistContent = GetRemoteContent(sizelistURL)
local treeContent = GetRemoteContent(treeURL)
local totalSizeBytes = 0
local totalSizeNonExistentBytes = 0
local fileList = {}
for filename in treeContent:gmatch("%s*(.-)%s*\n") do
if filename:sub(-4) == ".tcz" then
local sizeBytes = getFileSize(sizelistContent, filename)
totalSizeBytes = totalSizeBytes + sizeBytes
table.insert(fileList, {filename = filename, sizeBytes = sizeBytes})
end
end
local function formatSizeMB(sizeBytes)
return string.format("%.2f MB", sizeBytes / (1024 * 1024))
end
table.sort(fileList, function(a, b) return a.sizeBytes > b.sizeBytes end)
print(" Filename Size (bytes), Size (MB)")
print("------------------------------------------------------------------")
for _, fileData in ipairs(fileList) do
local filename = fileData.filename
local sizeBytes = fileData.sizeBytes
local fileExists = FileExist(filename)
if not fileExists then
filename = "+" .. filename
totalSizeNonExistentBytes = totalSizeNonExistentBytes + sizeBytes
end
print(string.format(" %-40s %12d, %15s", filename, sizeBytes, formatSizeMB(sizeBytes)))
end
print("\n Total size (bytes) " .. string.format("%12d, %15s", totalSizeBytes, formatSizeMB(totalSizeBytes)))
print(" + Indicates need to download " .. string.format("%12d, %15s", totalSizeNonExistentBytes, formatSizeMB(totalSizeNonExistentBytes)))
--- End code ---
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version