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. Commented Oct 14, 2013 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. Commented Oct 14, 2013 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 Commented Oct 14, 2013 at 21:29

8 Answers 8

11

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 
2
  • 5
    That command screws up all my fstab comments, but other than that, it does exactly what I'm looking for. :) Commented Oct 14, 2013 at 23:00
  • Use sed to then remove those extra spaces. Probably don't need this now but this still comes up in google searches as a high ranked search result so just adding for anyone else coming here. unix.stackexchange.com/questions/212450/… Commented Mar 13, 2024 at 10:45
4

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 
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

This function will format the mount information lines with column, and keep your comment lines intact.

formatFstab(){ # replace any whitespace or comment lines with an empty line clean_lines=$(sed -E 's/^\s*(#.*)?$//' /etc/fstab) # tabulate this content, keeping the empty lines table_content=$(column -tL <(printf '%s' "$clean_lines")) # column's empty lines are full of spaces, so make them truly empty clean_table_content=$(sed -r 's/^[[:space:]]*$//' <<< "$table_content") # interlace the original and new lines with paste # use awk to go through pairs of lines, and take the new content only if non-empty final_content=$(paste -d'\n' /etc/fstab <(printf '%s' "$clean_table_content") \ | awk 'NR%2==1{a=$0;next} $0==""{$0=a} 1') printf '%s' "$final_content" } 

For safety, you could check the changes it would make.

diff /etc/fstab <(formatFsTab) 

If you're happy with the changes, first back up.

cp /etc/fstab /etc/fstab.bak 

And then (in a redirect safe manner) either this

new_content_file=$(mktemp) \ && formatFstab > "$new_content_file" \ && cat "$new_content_file" > /etc/fstab \ && rm "$new_content_file" 

Or if you have sponge installed

formatFstab | sponge /etc/fstab 

Should work on any modern Linux system, but the column command's -L flag appears to be a GNU extension, so a different/altered solution might be required for BSD systems.

1

Here is a one-liner that will align your fstab. It requires the tool "sponge", which is for instance provided by the package "moreutils" on Debian.

cp /etc/fstab /etc/fstab.old ; column -t /etc/fstab | sed -e '/^#/ s/ \{1,\}/ /g' | sed -E 's/[ \t]+$//' | sponge /etc/fstab 

Here are the different parts and their roles:

cp /etc/fstab /etc/fstab.old 

Creates a backup of the file, just in case.

column -t /etc/fstab 

Aligns the fields as columns, including in comments, unfortunately.

sed -e '/^#/ s/ \{1,\}/ /g' 

Replaces multiple spaces in comments added by column by just one space. If you need some, well, it is going to break your comments. But usually it is OK.

sed -E 's/[ \t]+$//' 

Removes trailing spaces or tabs.

sponge /etc/fstab 

Writes back to /etc/fstab

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. Commented Oct 14, 2013 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. Commented Oct 14, 2013 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. Commented Oct 14, 2013 at 22:26
0

Late to the party, simple solution

cp /etc/fstab ~/oldfstab grep '^#' /etc/fstab > ~/newfstab grep -v '^#' /etc/fstab | column -t >> ~/newfstab cp ~/newfstab /etc/fstab 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.