Replace each leading tab with four spaces, recursively for each file

What's the easiest way to achieve this with common tools in Linux?

I watched:

  • sed

    but it is not enough to know how to count the overlapping leading tabs in a type expression sed -i 's/^[\t]*/<what-to-put-here?>/g myFile.c

    .
  • astyle

    but can't figure out how to tell about it only in reindent and NOT format
  • indent

    , same problem as astil
  • expand

    but it also replaces non-variable tabs and I have to handle the inplace replacement myself which is error prone.

I was just looking for a quick and easy solution that I can connect to find -type f -name "*.c" -exec '<tabs-to-spaces-cmd> {}' \;

+3


source to share


3 answers


This might work for you (GNU sed):



sed -ri ':a;s/^( *)\t/\1    /;ta' file

      

+2


source


You really should use expand

as it is designed just for that. From the documentation :

-i, --initial
   do not convert tabs after non blanks

      

So the command for one file would be:

expand -i -t 4 input > output

      



To use it with multiple files, you need a trick:

expand_f () {
  expand -i -t 4 "$1" > "$1.tmp"
  mv "$1.tmp" "$1"
}

export -f expand_f
find -type f -iname '*.c' -exec bash -c 'expand_f {}' \;

      

This is used to prevent expand

writing to the file while it is still processing it, and to not redirect stdout from find

and not from expand

.

+4


source


For a single line comand you can use expand -i

as the other answer describes, but to automate the process with the find command you can use:

find ... -exec sh -c 'expand -i -t 4 {} > {}-t && mv {}-t {}' ';'

      

The reason for using the tag cmd file > file-t && mv file-t file

is because the shell will delete the content file-t

after seeing the redirect. Therefore, if you used cmd file > file

, then you cmd

could only see an empty file.

0


source







All Articles