9

Editing /etc/fstab with my text editor makes all the spacing go out of alignment. I could go through the file and insert/delete spaces to line everything up, but I'm looking for a more automated solution. Ideally, there would be an online javascript page that I could put my fstab into, and have it "pretty" align everything. Then I could copy/paste the final result back into the file.

Is there a similar or better solution to this available?

EDIT:
I use Linux on my desktop, and I'm not seeking to join the religion of vi or emacs just to edit my fstab. Emacs might be a better solution for some people, but for some other people it's not a better solution.

EDIT2:
Here is an example snippet of my fstab using tabs. The columns are not in alignment.

proc    /proc   proc    nodev,noexec,nosuid 0   0
/dev/disk/by-label/Linux    /   ext4    errors=remount-ro   0   1
/dev/disk/by-label/Home /home   ext4    defaults    0   0

I want it to be automatically formatted with spaces and look more like the following.

proc                        /proc   proc    nodev,noexec,nosuid 0   0
/dev/disk/by-label/Linux    /       ext4    errors=remount-ro   0   1
/dev/disk/by-label/Home     /home   ext4    defaults            0   0
3
  • 1
    You could just set your text editor up to use sensible spacing... Vim works well for me.
    – jasonwryan
    Oct 14 '13 at 20:33
  • What editor are you using? Having an app for this is overkill. Works fine for me if I just use tabs to align in emacs.
    – terdon
    Oct 14 '13 at 20:41
  • I don't understand exactly your problem, you could post your /etc/fstab. Meanwhile, you could try: cp /etc/fstab /etc/fstab.backup && grep -v "#" /etc/fstab | sed -r 's/( )+/\\t/g' > /etc/fstab HTH
    – sebelk
    Oct 14 '13 at 21:29
9

I like to use the column command with the -t option for aligning columns into a nice table:

column -t /etc/fstab
proc                      /proc  proc  nodev,noexec,nosuid  0  0
/dev/disk/by-label/Linux  /      ext4  errors=remount-ro    0  1
/dev/disk/by-label/Home   /home  ext4  defaults             0  0
1
  • 3
    That command screws up all my fstab comments, but other than that, it does exactly what I'm looking for. :)
    – Sepero
    Oct 14 '13 at 23:00
2
#!/bin/bash
# usage: fstabalign [FILE]

# This script will output fstab or other file as column aligned.
# It will not alter blank lines or #hash comments.

if [ -z "$1" ]; then
    FILE=$(cat /etc/fstab)
else
    FILE=$(cat "$1")
fi

# Separate the file contents into aligned and unaligned parts.
OUT_ALIGNED=$(echo "$FILE" | sed 's/^\s*#.*//' | nl -ba | column -t)
OUT_UNALIGNED=$(echo "$FILE" | sed 's/^\s*[^#].*//' $src | nl -ba)

# Remerge aligned and unaligned parts.
while read; do
    line_aligned="$REPLY"
    read -u 3; line_unaligned="$REPLY"
    line_aligned=$(  echo "$line_aligned"   | sed 's/\s*[0-9]*\s*//')
    line_unaligned=$(echo "$line_unaligned" | sed 's/\s*[0-9]*\s*//')
    echo "$line_aligned$line_unaligned"
done < <(echo "$OUT_ALIGNED") 3< <(echo "$OUT_UNALIGNED")
1

EDIT:

Ah, didn't notice your no Vim edit until now.

An alternative could be to put something like this in a script.

It goes like this:

  1. Extract entries only, keep empty lines where comments are.
  2. Pipe it to column and use -e to keep empty lines, save to temporary file 1.
  3. Extract comments, save to temporary file 2.
  4. Merge files using paste with -d'\0' to discard spaces at beginning.

Save to file, chmod +x script_file and run as ./script_file. Optionally specify fstab file by ./script_file /path/to/fstab/file.

Looks OK? Then ./script_file > /etc/fstab

#!/bin/bash

src="/etc/fstab"

[[ "$1" ]] && src="$1"

[[ -r "$src" ]]  || exit 1
tmp1="$(mktemp)" || exit 1
tmp2="$(mktemp)" || exit 1

# Filter out comments and pipe them through column with -e
# Save to tmp1
sed 's/^[ \t]*#.*//' "$src" | column -et > "$tmp1"

# Filter out tab lines and save to tmp2
sed 's/^[ \t]*[^#].*//' "$src" > "$tmp2"

# merge
paste -d'\0' "$tmp1" "$tmp2"

rm "$tmp1" "$tmp2"

Vim:

You could use a Vim script. This is a rewrite from a similar thing ...

  • Adds a new command :FmtFstab
  • Comment lines starting with magic #= is also formatted. (Thus if you comment out a fstab line and want it formatted, use #= at start of line. No spaces after #= and entry!).

Add to a script file that gets loaded, or load it manually by

:so file_name.vim

When file open in Vim, simply say :FmtFstab, and it get formatted. Also formats header accordingly.

(I also have a script that inserts or list UUID's if that is of interest.)

" Split string by pattern
" Return array/List in form : [ length, [len_match1, len_match2, ...] ]
fun! s:StrSplit2Widths(line, pat)
    let lst=split(a:line, a:pat)
    call map(lst, 'strlen(v:val)')
    return [len(lst), lst]
endfun

" Generate a string based on a "widths" list
" @widths: widths to use for each entry in list (format as from
"          s:StrSplit2Widths)
" @lst   : list with text to be printed according to widths
fun! s:WidthFmtList(widths, lst)
    let i = len(a:lst) - 1
    let lif=""
    while i >= 0
        let lif = printf("%-*s", a:widths[1][i], a:lst[i]) . " " . lif
        let i = i - 1
    endwhile
    return lif
endfun

" Format current line according to widths
fun! s:FmtBufLine(widths)
    let lst=split(getline("."), '\s\+')
    if a:widths[0] != len(lst)
        return
    endif

    let lif = s:WidthFmtList(a:widths, lst)

    call setline(line("."), lif)
endfun

fun! <SID>:FormatFstab(...)
    " Comments to include
    let incmagic = "#="
    " Header
    let hdr    = "# <file system> <mount point> <type> <options> <dump> <pass>"
    " Base widths are based on header
    let widths = s:StrSplit2Widths(hdr, '>\zs\s*\ze<')
    " Get all lines (this can be expanded to only do ranges)
    let lines  = getline(1, line("$"))

    " Remove all lines not matching pattern
    call filter(lines, 'v:val =~ "^\\s*\\([^#]\\|' . incmagic . '\\)"')

    " Calculate width for each column
    for line in lines
        let lw = s:StrSplit2Widths(line, '\s\+')
        while lw[0] < widths[0]
            call add(lw[1], 0)
            let lw[0] = lw[0] + 1
        endwhile
        call map(widths[1], 'lw[1][v:key] > v:val ? lw[1][v:key] : v:val')
    endfor

    " Format each line matching pattern
    silent exec ':g/^\s*\(' . incmagic . '\|[^#]\)/ call s:FmtBufLine(widths)'

    " Format header
    let hlst = split(hdr, '>\zs\s*\ze<')
    silent :%s/^\s*#\s*<file system>.*/\=s:WidthFmtList(widths, hlst)
endfun

" ex command
command! -nargs=0 -bar FmtFstab call <SID>:FormatFstab()
1

I actually prefer no alignment at all (just a single space). But it's an interesting problem. I wonder why column doesn't have an option for this, seems like a perfect use case...

Aligning the entire fstab would lead to very long lines, at least in my case, as I have some filesystems with special options, and also some very long disk-by-id device paths. So I wrote a script that aligns each section (divided by empty lines or comment lines) individually.

Using ./fstab.sh /etc/fstab:

#!/bin/bash

function push() {
    buffer="$buffer"$'\n'"$1"
}

function pop() {
    if [ "$buffer" != "" ]
    then
        echo "$buffer" | column -t
        buffer=""
    fi
}

buffer=""

while read line
do
    if [ "$line" == "" -o "${line:0:1}" == "#" ]
    then
        pop
        echo "$line"
    else
        push "$line"
    fi
done < "$1"

pop

Before:

# /etc/fstab: static file system information.
# <fs> <mountpoint> <type> <opts> <dump/pass>

# --- SPECIAL ---

none /dev/shm tmpfs nosuid,nodev,noexec,noatime 0 0
none /tmp tmpfs noatime,nosuid,nodev 0 0
none /var/tmp/portage tmpfs noatime,mode=0750,gid=portage,uid=portage 0 0

# --- INTERNAL ---

# SSD
UUID=fa15678f-7e7e-4a47-8ed2-7cea7a5d037d / xfs noatime 0 0
UUID=529cc283-53bc-4acc-a4d3-f35278d3f2f9 /home xfs noatime 0 0

# HDD
UUID=d7562145-654c-48bb-b8d2-1552a69186f5 /home/TV xfs noatime 0 0
UUID=952b5dee-8d2a-40b2-85f9-5e5092bc1e75 /home/steam xfs noatime 0 0
UUID=4dcb18c3-f3a5-4b03-8877-063c5cd836e4 /home/jn xfs noatime 0 0
UUID=c735614a-f5f3-4232-911f-8a17cb033521 /var/www xfs noatime 0 0
/dev/HDD/windows7 /mnt/windows7 ntfs-3g offset=105906176,noauto,noatime 0 0

# HDD (OLD)
UUID=23deb461-bab5-45b7-9dca-9c2c4cdb4f50 /mnt/HDD/OLD-home xfs noauto,noatime 0 0
UUID=dd1e1eef-b548-4c94-8ebe-99dd7a648cb0 /mnt/HDD/OLD-music xfs noauto,noatime 0 0
UUID=2ae11a11-db04-4d27-a79e-d9b07dd19650 /mnt/HDD/OLD-opt xfs noauto,noatime 0 0
UUID=2abb2a27-2183-488e-8c24-e195ab3dcb5d /mnt/HDD/OLD-portage xfs noauto,noatime 0 0
UUID=3d0030f0-92da-4e66-8e60-369dfc586df7 /mnt/HDD/OLD-portage_tmp xfs noauto,noatime 0 0
UUID=89200c49-2fc2-45ed-81c8-e244b95db7ce /mnt/HDD/OLD-root xfs noauto,noatime 0 0
UUID=caebfb75-6a1c-4ed6-ad2f-d84d80221dc3 /mnt/HDD/OLD-schrott xfs noauto,noatime 0 0
UUID=cabddcee-cf07-4526-b3a3-9270edc9d171 /mnt/HDD/OLD-src xfs noauto,noatime 0 0
UUID=a2e4df4e-8c6d-4217-8889-6f483e872190 /mnt/HDD/OLD-tmp xfs noauto,noatime 0 0
UUID=4dd484f6-4142-45b3-b504-48625de1ab5c /mnt/HDD/OLD-var xfs noauto,noatime 0 0

# ODD
/dev/sr0 /mnt/cdrom auto user,noauto,ro 0 0

# --- EXTERNAL ---

# USB-Boot-Stick
LABEL="boot_key" /boot ext2 noauto,noatime 0 0
LABEL="boot_dos" /mnt/boot/dos vfat noauto,noatime 0 0
LABEL="boot_iso" /mnt/boot/iso ext2 noauto,noatime 0 0
LABEL="live0" /mnt/boot/live0 ext2 noauto,noatime 0 0
LABEL="live1" /mnt/boot/live1 ext2 noauto,noatime 0 0

# iriver Story HD
/dev/disk/by-id/usb-iriver_Story_EB07_3230204E6F76-0:0 /mnt/iriver/knv auto user,noauto,noatime 0 0
/dev/disk/by-id/usb-iriver_Story_SD_3230204E6F76-0:1 /mnt/iriver/ext auto user,noauto,noatime 0 0

# Sandisk Sansa CLIP
UUID=C65F-1E04 /mnt/mp3 auto user,noauto,noatime 0 0

# Eltern-Fernseher
UUID=115BF67A31CB6C02 /mnt/wdtv ntfs-3g locale=en_US.utf8,user,noauto 0 0
UUID=D27A-7C74 /mnt/pvr vfat user,noauto,noatime 0 0

After:

# /etc/fstab: static file system information.
# <fs> <mountpoint> <type> <opts> <dump/pass>

# --- SPECIAL ---

none  /dev/shm          tmpfs  nosuid,nodev,noexec,noatime                0  0
none  /tmp              tmpfs  noatime,nosuid,nodev                       0  0
none  /var/tmp/portage  tmpfs  noatime,mode=0750,gid=portage,uid=portage  0  0

# --- INTERNAL ---

# SSD
UUID=fa15678f-7e7e-4a47-8ed2-7cea7a5d037d  /      xfs  noatime  0  0
UUID=529cc283-53bc-4acc-a4d3-f35278d3f2f9  /home  xfs  noatime  0  0

# HDD
UUID=d7562145-654c-48bb-b8d2-1552a69186f5  /home/TV       xfs      noatime                          0  0
UUID=952b5dee-8d2a-40b2-85f9-5e5092bc1e75  /home/steam    xfs      noatime                          0  0
UUID=4dcb18c3-f3a5-4b03-8877-063c5cd836e4  /home/jn       xfs      noatime                          0  0
UUID=c735614a-f5f3-4232-911f-8a17cb033521  /var/www       xfs      noatime                          0  0
/dev/HDD/windows7                          /mnt/windows7  ntfs-3g  offset=105906176,noauto,noatime  0  0

# HDD (OLD)
UUID=23deb461-bab5-45b7-9dca-9c2c4cdb4f50  /mnt/HDD/OLD-home         xfs  noauto,noatime  0  0
UUID=dd1e1eef-b548-4c94-8ebe-99dd7a648cb0  /mnt/HDD/OLD-music        xfs  noauto,noatime  0  0
UUID=2ae11a11-db04-4d27-a79e-d9b07dd19650  /mnt/HDD/OLD-opt          xfs  noauto,noatime  0  0
UUID=2abb2a27-2183-488e-8c24-e195ab3dcb5d  /mnt/HDD/OLD-portage      xfs  noauto,noatime  0  0
UUID=3d0030f0-92da-4e66-8e60-369dfc586df7  /mnt/HDD/OLD-portage_tmp  xfs  noauto,noatime  0  0
UUID=89200c49-2fc2-45ed-81c8-e244b95db7ce  /mnt/HDD/OLD-root         xfs  noauto,noatime  0  0
UUID=caebfb75-6a1c-4ed6-ad2f-d84d80221dc3  /mnt/HDD/OLD-schrott      xfs  noauto,noatime  0  0
UUID=cabddcee-cf07-4526-b3a3-9270edc9d171  /mnt/HDD/OLD-src          xfs  noauto,noatime  0  0
UUID=a2e4df4e-8c6d-4217-8889-6f483e872190  /mnt/HDD/OLD-tmp          xfs  noauto,noatime  0  0
UUID=4dd484f6-4142-45b3-b504-48625de1ab5c  /mnt/HDD/OLD-var          xfs  noauto,noatime  0  0

# ODD
/dev/sr0  /mnt/cdrom  auto  user,noauto,ro  0  0

# --- EXTERNAL ---

# USB-Boot-Stick
LABEL="boot_key"  /boot            ext2  noauto,noatime  0  0
LABEL="boot_dos"  /mnt/boot/dos    vfat  noauto,noatime  0  0
LABEL="boot_iso"  /mnt/boot/iso    ext2  noauto,noatime  0  0
LABEL="live0"     /mnt/boot/live0  ext2  noauto,noatime  0  0
LABEL="live1"     /mnt/boot/live1  ext2  noauto,noatime  0  0

# iriver Story HD
/dev/disk/by-id/usb-iriver_Story_EB07_3230204E6F76-0:0  /mnt/iriver/knv  auto  user,noauto,noatime  0  0
/dev/disk/by-id/usb-iriver_Story_SD_3230204E6F76-0:1    /mnt/iriver/ext  auto  user,noauto,noatime  0  0

# Sandisk Sansa CLIP
UUID=C65F-1E04  /mnt/mp3  auto  user,noauto,noatime  0  0

# Eltern-Fernseher
UUID=115BF67A31CB6C02  /mnt/wdtv  ntfs-3g  locale=en_US.utf8,user,noauto  0  0
UUID=D27A-7C74         /mnt/pvr   vfat     user,noauto,noatime            0  0
0

Vim should work or emacs. Heck even nano should display fstab correctly. If you are wanting to use a text editor GUI then you could try gedit. If you really do want to put your fstab in an online editor then you could use google docs (and then copy paste back).

Make sure that you are using tabs to space your fstab and not single spaces. That could cause inconsistencies, especially if you are using a little bit of both.

It's possible that it looks funky because the shell window isn't large enough to fit the entire text in the line.

3
  • Thanks for your answer. I think perhaps I'm being a bit misunderstood. The ability of my desired solution to edit fstab would be optional. The primary thing I'm looking for it to do is align all the columns. I don't have any problem editing fstab. I'd just like something to "clean it up" when I'm finished.
    – Sepero
    Oct 14 '13 at 22:15
  • If you are using the tab key when spacing your columns there shouldn't be any need to clean anything up because the columns will already be aligned. I work with many servers and all the columns on all the fstabs align because I'm using tab to keep the spacing the same. I don't see the purpose of an app to do something that's already being done. Sorry I couldn't help more.
    – Jeight
    Oct 14 '13 at 22:21
  • Ah yes, I see what you mean. Using tabs to align the columns would be faster than spaces, but for any column longer than 8 characters, it still requires manual alignment fixing. So this is what I'm trying to avoid. I appreciate your help.
    – Sepero
    Oct 14 '13 at 22:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.