By design, GitHub automatically converts all leads from tabs to spaces when you re-edit a file with leading tabs: That is, if you edit a file, changing all leads from spaces to tabs, it will be saved this way, but if you re-edit the file and save (without changing leads), all leads will be automatically converted back to spaces.

1) File edit mode before saving the changes:

enter image description here

2) File edit after saving the changes:

enter image description here

Note how it went back from tabs (4), to spaces (2), just when I came to re-edit the file.

Why that's a problem

Execution of raw versions of remote scripts with curl, containing tab-dependent data (like here-documents), will fail. Their execution will just break with some error because they must contain leading tabs and not spaces.

That's the basic curl pattern I use to execute remote scripts from GitHub is the following (For multiple curl, this one.):

curl -s URL | tr -d '\r' | bash

My question

Is there a way (probably with tr) to change all leading spaces into tabs, to make sure that remote scripts I run from GitHub will always have leading tabs instead spaces, thus not effected by this strange behavior of GitHub?


1 Answer 1


I can't say much about GitHub and its editor as I never edit GitHub files directly in the web interface.

The standard utilities expand and unexpand may be used to convert leading tabs into spaces (expand) or leading spaces into tabs (unexpand).

To change the leading two spaces into a tab (or four spaces into two tabs etc.), use

unexpand -t 2 file

This can also be used as a filter as in

somecommand | unexpand -t 2

To replace any number of leading spaces with a single tab, one could also use GNU sed like so:

sed 's/^  */\t/'

The pattern is ^ * with two spaces between the ^ and the *. This regular expression will match one or more leading spaces (equivalent of ^ + or ^ {1,} if using GNU sed with -r or -E). The GNU sed substitution will replace these with a tab (other implementations of sed will need a literal tab character in the replacement part, instead of \t).

I'm noticing that this will not work on OpenBSD as its implementation of unexpand assumes eight spaces per tab and won't recognize the -t flag. The above suggestion works with unexpand as found in GNU coreutils though.

  • I just read man unexpand: unexpand -t 2 --first-only file is what I need! Thanks! But small note - some files have 2/4/6/8 tabs. Is there a wildcard to gather all? Can regex be added somehow? Feb 10, 2018 at 12:37
  • 1
    @user9303970 See updated answer.
    – Kusalananda
    Feb 10, 2018 at 12:51
  • 1
    @user9303970 As far as I know, --first-only will only be needed to negate the effect of an earlier --all (-a) flag.
    – Kusalananda
    Feb 10, 2018 at 12:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .