Screenshot from Terminal

Linux-mint is my choice of Linux distro. I can focus on my things to do without having to care about much of device drivers and other nitty gritty stuff just to start to use the OS.

I was wondering a screen capture tool on it. I purchase SnagIt license for screen capture but I don’t think it is available on Linux. I found a nice command line tool called scrot. To install it…

sudo apt-get install scrot

If you want to select certain area by mouse, execute the following

scrot --select

Here is the example of a capture.

If you want to capture a different tab and need a bit of a delay, you can use sleep command to give yourself a bit of time before it is in a capture mode.

sleep 5;scrot --select

This means you have it wait for 5 seconds before you execute scrot command.

The screen capture files are saved in our home directory.

This tool is very impressive. It can do pretty much what you need it to do getting images for your documentations and other purposes.

Linus’ Interview

I love this guy and have so much respect as an engineer. Windows is Bill Gates, Mac is Steve Jobs and Linux is Linus Torvals. He may not be the nicest person but his love for technology inspires me.

I got into the software engineering field by admiring Bill Gates, then I got to respect Steve Jobs for throwing away OS 9 and totally Unix-ize Mac OS X (then macOS) because that was the game changer for Apple and then Linus Torvals because I use Linux for work and it’s the OS that lights the Internet.

My interest in technology just does not go away after 22 years of my career. It’s still exciting!

Round to the Nearest Multiple of 5

I needed a code snippet that can get the nearest multiple of 5 based on a number.

For example, 11 should be 15, 16 should be 20, 26 should be 30 and so forth.

11 -> 15
16 -> 20
26 -> 30

Here is the way to think about this problem. So the final result should be multiple of 5, so if the original number is divided by 5, the remainder should be 0, 1, 2, 3 or 4. If you divide 11 by 5, the remainder is 4. If you add this 4 to 11, you get the nearest multiple of 5. So to generalize this to an equation…

original_num = 11
result = original_num + original_num % 5

It’s really easy when you think about it, but if you have not gone through a problem like this before, maybe it’s hard to come up with the idea to use remainder.

checksum for files

Each file can have a finger print depending on its content. The finger print is called checksum. If 2 files have exactly the same content, those 2 files would have the same checksum. We can use md5 on Mac and md5sum on Linux.

I have a file “~/tmp/data.txt”. It’s checksum can be calculated with the following command.

md5 data.txt

Result

MD5 (data.txt) = e1e1415d2433143ff43103b384df7402

I’m going to copy the file as data2.txt and have it calculate the checksum.

To copy…

cp data.txt data2.txt

Then I’m going to pass 2 files to md5 command.

md5 data.txt data2.txt

Result

MD5 (data.txt) = e1e1415d2433143ff43103b384df7402
MD5 (data2.txt) = e1e1415d2433143ff43103b384df7402

As you can see, the hashes are exactly the same. This is really useful to see if the files are exactly the same or not.

You could implement a process to calculate the hash locally and then the files are uploaded to the production systems, you could have another process on the server side to make sure the uploaded files have the same hash.

You could alternatively combine find command and md5 command to have it calculate the selected files like the following.

find . -name 'data*' | xargs md5

Result

MD5 (./data2.txt) = e1e1415d2433143ff43103b384df7402
MD5 (./data.txt) = e1e1415d2433143ff43103b384df7402

And when the same file is copied to another system from Mac to Linux (I have a Linux-Mint machine) and execute md5sum on the file, I get exactly the same md5 hash.

How to Check the Size of Directories

If you want to see how much data a directory contains. Here is the command you can use.

du -sh dev

Result

746M dev

If you want to see the size of all the directory sizes…

du -sh *

Result

4.0K	2020-07-21-06-12-49.081-VBoxSVC-7899.log
34M	apps
241M	bin
48K	CA
175M	data
4.0K	Desktop
746M	dev
86G	Documents
4.6G	Downloads
4.0K	id_rsa
4.0K	id_rsa.pub
4.0K	Music
4.0K	Pictures
4.0K	Public
4.0K	Templates
90M	tmp
4.0K	Videos
0	VMs

Let’s take it a little further. What if you want to check the sizes of directories up to the second level? Here is the command you can use.

sudo du -h --max-depth=2

Result

8.0K ./.vim
4.0K ./.gnupg/private-keys-v1.d
8.0K ./.gnupg
4.0K ./Videos
620M ./dev/docker
4.0K ./Public
4.0K ./Templates
2.6G ./.local/share
2.6G ./.local
4.0K ./Pictures
<SNIP>
19M ./.mozilla/firefox
19M ./.mozilla
8.0K ./.hplip
4.0K ./Desktop
428K ./.mozc
7.1M ./tmp/nginx-1.18.0
34M ./tmp/sublime_text_3
50M ./tmp/docker-rootless-extras
90M ./tmp
96G .

Regex and For Loop in Python

In this blog article, I will introduce the way for Python to parse the file by using regular expression to deal with the data in a text file.

1 = hoge1
2 = hoge2
3 = foo1
4 = foo2
5 = foo3

Let’s image this data in stored in a text file data.txt and the Python script that I’m going to write will read the text file and loop through each line and then turn the raw data into a dictionary data.

import re

if __name__ == '__main__':
    data_file = '/Users/hiriumi/tmp/data.txt'
    f = open(data_file, 'r')

    data = f.read()
    f.close()

    data_parse_re = re.compile(r'(\d)\s*=\s*(.+)')
    dict_data = {} # create an empty dict object
    for num, val in data_parse_re.findall(data):
        dict_data[num] = val

    print(dict_data)

Result below.

{'1': 'hoge1', '2': 'hoge2', '3': 'foo1', '4': 'foo2', '5': 'foo3'}

You might wonder where do num and val come from in the for loop? If you take a look at the regex, it has 2 sets of parenthesis. num maps to the result of the match of within the first parenthesis which is \d. It means a number in this case. val maps to the match of the regex of the second parenthesis which is .+. It means one or more (+) of any character (.).

If you have 3 sets of parenthesis, you can add another variable in the for loop to extract the value.

Let’s take it one step further. If you want a zero based index, you could wrap the result of findall() method with enumerate(). Here is the example.

import re

if __name__ == '__main__':
    data_file = '/Users/hiriumi/tmp/data.txt'
    f = open(data_file, 'r')

    data = f.read()
    f.close()

    data_parse_re = re.compile(r'(\d)\s*=\s*(.+)')
    for num, item in enumerate(data_parse_re.findall(data)):
        print(num, item[0], item[1])

The content of item is a tuple. The first element maps to the match of the first element and the second element maps to the match of the second element. It goes without saying that if there was a third set of parenthesis, it would put the value to the third item in the tuple. This way, you don’t need to maintain another variable and increment it for each iteration of the loop.

I find this quite useful when I have to parse logs. You might struggle with it but I believe it is very important to be adequate at regular expression as a software engineer.

Anonymous Type in Python

Anonymous type is a useful feature in C#. Here is the example from the Microsoft’s site.

var v = new { Amount = 108, Message = "Hello" };
  
// Rest the mouse pointer over v.Amount and v.Message in the following  
// statement to verify that their inferred types are int and string.  
Console.WriteLine(v.Amount + v.Message);

You don’t have to have a class with bunch of attributes beforehand to create an object. The same kind of technique can be done with Python and I’ve actually used it at work.

class Data(dict):
    __getattr__, __setattr__ = dict.get, dict.__setitem__


if __name__ == '__main__':
    v = Data(Amount=108, Message="Hello")
    print(f"{v.Amount}{v.Message}")

You do need to prepare a class that inherits from dict but that’s just two lines.

You could have a list of the objects and even sort them. Here is an example.

class Data(dict):
    __getattr__, __setattr__ = dict.get, dict.__setitem__


if __name__ == '__main__':
    records = []
    records.append(Data(Amount=108, Message="a"))
    records.append(Data(Amount=101, Message="b"))
    records.append(Data(Amount=99, Message="c"))
    records.append(Data(Amount=110, Message="d"))
    records.append(Data(Amount=111, Message="e"))
    records.append(Data(Amount=91, Message="c"))

    # Sort by Amount
    records = sorted(records, key=lambda record: record.Amount)
    print(records)

    # Sort by Message
    records = sorted(records, key=lambda record: record.Message)
    print(records)

If you have multiple attribute to sort by, you can list the attributes in a comma delimited way.

Sorting Python dictonary

Python has quite a nice mechanism for sorting. Here is an example to sort a list of integers.

a = [1, 5, 11, 6, 7, 2, 10, 4]
a = sorted(a)
print(a)

Result

[1, 2, 4, 5, 6, 7, 10, 11]

This is really easy but sorting a dictionary by key is a little more complicated. Here is an example.

data = {1: 'e', 5: 'a', 3: 'b', 2: 'c', 4: 'd'}
sorted_data = sorted(data.items(), key=lambda item: item[0])

for k, v in sorted_data.items():
    print(f"{k}: {v}")

Result

1: e
2: c
3: b
4: d
5: a

Now let’s try to sort by value.

data = {1: 'e', 5: 'a', 3: 'b', 2: 'c', 4: 'd'}
sorted_data = sorted(data.items(), key=lambda item: item[1])

for k, v in sorted_data:
    print(f"{k}: {v}")

Result

5: a
3: b
2: c
4: d
1: e

It uses lambda. This means this method could be used for different types of object. In my next blog, I will talk about anonymous type of object in Python and sorting list of objects.

Output a Number to 2 Decimal Points

I should remember how to do this.

So you have 3.141592653 in a variable and you want to output up to the 2 decimal points. Here is how you can do it.

a = 3.141592653
print("{:.2f}".format(a))

The code above returns string. If you want to convert it to an actual float value, you can surround it with float.

Here is a Python3 way. This is cleaner.

print(f"{a:.2f}")