As we have seen before, we can convert /etc/fstab
(or mtab
)
to e.g. an XML or a nice and colorful table using Relational pipes.
But we can also convert these data back to the fstab
format. And do it with proper indentation/padding.
Fstab has a simple format where values are separated by one or more whitespace characters.
But without proper indentation, these files look a bit obfuscated and hard to read (however, they are valid).
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/vda1 during installation
UUID=29758270-fd25-4a6c-a7bb-9a18302816af / ext4 relatime,user_xattr,errors=remount-ro 0 1
/dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0
/dev/sde /mnt/data ext4 relatime,user_xattr,errors=remount-ro 0 2
UUID=a2b5f230-a795-4f6f-a39b-9b57686c86d5 /home btrfs relatime 0 2
/dev/mapper/sdf_crypt /mnt/private xfs relatime 0 2
So let's build a pipeline that reformats the fstab
and makes it more readable.
relpipe-in-fstab | relpipe-out-fstab > reformatted-fstab.txt
We can hack together a script called relpipe-out-fstab
that accepts relational data and produces fstab
data.
Later this will be probably implemented as a regular tool, but for now, it is just an example of a ad-hoc shell script:
#!/bin/bash
(
# Just troll-in the first record:
relpipe-in-cli \
--relation "Heathers" \
--attribute "Duke" string \
--attribute "McNamara" string \
--attribute "Chandler" string \
--attribute "Veronica" string \
--attribute "J.D." string \
--attribute "Big" string \
--attribute "Fun" string \
--record \
'' '# <file system>' '<mount point>' '<type>' '<options>' '<dump>' '<pass>';
# relpipe-out-nullbyte processes only attribute values
# Read the actual pipe's input:
cat
) | relpipe-out-nullbyte \
| xargs --null --max-args=7 perl -e \
'printf("%-*s %-*s %-*s %-*s %-*s %s\n",
# following numbers define paddings:
50, ($ARGV[0] eq "" ? $ARGV[1] : "$ARGV[0]=$ARGV[1]"),
40, ($ARGV[2] eq "" ? "none" : $ARGV[2]),
16, $ARGV[3],
50, $ARGV[4],
8, $ARGV[5],
$ARGV[6]
);'
Download: examples/relpipe-out-fstab.sh
In the first part, we prepend a single record (relpipe-in-cli
) before the data coming from STDIN (cat
).
Then, we use relpipe-out-nullbyte
to convert relational data to values separated by a null-byte.
This command processes only attribute values (skips relation and attribute names).
Then we used xargs
to read the null-separated values and execute a Perl command for each record (pass to it a same number of arguments, as we have attributes: --max-args=7
).
Perl does the actual formatting: adds padding and does some little tunning (merges two attributes and replaces empty values with none).
This is formatted version of the fstab
above:
# <file system> <mount point> <type> <options> <dump> <pass>
UUID=29758270-fd25-4a6c-a7bb-9a18302816af / ext4 relatime,user_xattr,errors=remount-ro 0 1
/dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0
/dev/sde /mnt/data ext4 relatime,user_xattr,errors=remount-ro 0 2
UUID=a2b5f230-a795-4f6f-a39b-9b57686c86d5 /home btrfs relatime 0 2
/dev/mapper/sdf_crypt /mnt/private xfs relatime 0 2
And using following command we can verify, that the files differ only in comments and whitespace:
relpipe-in-fstab | relpipe-out-fstab | diff -w /etc/fstab -
Another check (should print same hashes):
relpipe-in-fstab | sha512sum relpipe-in-fstab | relpipe-out-fstab | relpipe-in-fstab | sha512sum
Regular implementation of relpipe-out-fstab
will probably keep the comments
(it needs also one more attribute and small change in relpipe-in-fstab
).
For just mere fstab
reformatting, this approach is a bit overengineering.
We could skip the whole relational thing and do just something like this:
cat /etc/fstab | grep -v '^#' | sed -E 's/\s+/\n/g' | tr \\n \\0 | xargs -0 -n7 ...
plus prepend the comment (or do everything in Perl).
But this example is intended as a demostration, how we can
1) prepend some additional data before the data from STDIN
2) use Relational pipes and traditional tools like xargs
or perl
together.
And BTW we have implemented a (simple but working) relpipe output filter – and did it without any serious programming, just put some existing commands together :-)
There is more Unix-nature in one line of shell script than there is in ten thousand lines of C. 1
Relational pipes, open standard and free software © 2018-2022 GlobalCode