fstab_beautifier.pl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #!/usr/bin/perl
  2. # Author: Daniel "Trizen" Șuteu
  3. # License: GPLv3
  4. # Date: 21 March 2014
  5. # https://trizenx.blogspot.com
  6. # Realign the columns of a space-delimited file (with support for comments and empty lines)
  7. use 5.010;
  8. use strict;
  9. use warnings;
  10. sub fstab_beautifier {
  11. my ($fh, $code) = @_;
  12. my @data;
  13. while (defined(my $line = <$fh>)) {
  14. if ($line =~ /^#/) { # it's a comment
  15. push @data, {comment => $line};
  16. }
  17. elsif (not $line =~ /\S/) { # it's an empty line
  18. push @data, {empty => ""};
  19. }
  20. else { # hopefully, it's a line with columns
  21. push @data, {fields => [split(' ', $line)]};
  22. }
  23. }
  24. # Indicate the EOF (this is used to flush the buffer)
  25. push @data, {eof => 1};
  26. # Store the columns and the width of each column
  27. my @buffer;
  28. my @widths;
  29. for (my $i = 0 ; $i <= $#data ; $i++) {
  30. my $line = $data[$i];
  31. if (exists $line->{fields}) { # it's a line with columns
  32. # Collect the maximum width of each column
  33. while (my ($i, $item) = each @{$line->{fields}}) {
  34. if ((my $len = length($item)) > ($widths[$i] //= 0)) {
  35. $widths[$i] = $len;
  36. }
  37. }
  38. # Store the line in the buffer
  39. # and continue looping to the next line
  40. push @buffer, $line->{fields};
  41. next;
  42. }
  43. elsif (exists $line->{comment}) { # it's a comment
  44. $code->(unpack("A*", $line->{comment}));
  45. }
  46. if (@buffer) { # buffer is not empty
  47. # Create the format for 'sprintf'
  48. my $format = join("\t", map { "%-${_}s" } splice(@widths));
  49. # For each line of the buffer, format it and send it further
  50. while (defined(my $line = shift @buffer)) {
  51. $code->(unpack("A*", sprintf($format, @{$line})));
  52. }
  53. }
  54. if (exists $line->{empty}) { # empty line
  55. $code->($line->{empty});
  56. }
  57. }
  58. }
  59. my $fh = @ARGV
  60. ? do {
  61. open my $fh, '<', $ARGV[0]
  62. or die "Can't open file `$ARGV[0]' for reading: $!";
  63. $fh;
  64. }
  65. : \*DATA;
  66. # Call the function with a FileHandle and CODE
  67. fstab_beautifier($fh, sub { say $_[0] });
  68. __END__
  69. # My system partitions
  70. /dev/sda7 swap swap defaults 0 0
  71. /dev/sda1 / ext3 defaults 1 1
  72. /dev/sda2 /home ext3 defaults 1 2
  73. # My /mnt partitions
  74. /dev/sr0 /mnt/dvd_sr0 auto noauto,user,ro 0 0
  75. /dev/sr1 /mnt/dvd_sr1 auto noauto,user,ro 0 0
  76. /dev/fd0 /mnt/floppy auto rw,noauto,user,sync 0 0
  77. /dev/sdd4 /mnt/zip vfat rw,noauto,user,sync 0 0
  78. /dev/sde1 /mnt/usb auto rw,noauto,user,sync 0 0
  79. # My /home/vtel57/ partitions
  80. /dev/sda8 /home/vtel57/vtel57_archives ext2 defaults 0 2
  81. /dev/sdc1 /home/vtel57/vtel57_backups ext2 defaults 0 2
  82. /dev/sdc7 /home/vtel57/vtel57_common vfat rw,gid=users,uid=vtel57 0 0
  83. # My /dev partitions
  84. devpts /dev/pts devpts gid=5,mode=620 0 0
  85. proc /proc proc defaults 0 0
  86. tmpfs /dev/shm tmpfs defaults 0 0