Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have a lot of files with tabs littered throughout, and I'd like to convert them all into spaces. I know about the expand command, but unfortunately I would have to type out every single file using it. Is there any easier way to do this on Linux?

share|improve this question
add comment

4 Answers

This is better:

find . -name *.java ! -type d -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;
share|improve this answer
    
Why is this better? It's not a great idea to use /tmp/e because if anything else is using that file, this will mess it up. Like if two users wanted to use this at the same time. –  Kevin Panko Mar 8 at 17:35
add comment
find . -type f -iname "*.js" -print0 | xargs -0 -I foo tab2space foo foo

-I foo creates a template variable foo for each input line, so you can refer to the input more than once.

-print0 and -0 tell both commands to use \0 as a line separator instead of SPACE, so this command works for paths with spaces.

share|improve this answer
add comment

Try the following:

find ./ -type f -exec sed -i 's/\t/ /g' {} \;

If you want four spaces, try:

find ./ -type f -exec sed -i 's/\t/    /g' {} \;
share|improve this answer
    
That will replace each tab by a single space. Since person mentioned using expand, I assume s/he wants the alignment of the text preserved. –  garyjohn Jul 2 '10 at 5:27
    
You need to have 's/\t/ /g' to replace more than just one tab per line. –  Daniel Andersson Mar 28 '12 at 20:49
    
@DanielAndersson: Thanks, edited! –  Nicolas Raoul Mar 29 '12 at 5:00
    
A substantial speedup if there are many files is doing "find ./ -type f -exec sed -i ’s/\t/ /g’ {} +" (that is, "+" instead of "\;"), if the find version supports it (and I haven't personally met any version that doesn't, but it's not a POSIX standard, so I guess it could happen on some systems. See "-exec command {} +" in the manual). Instead of launching one instance of sed for every file, this will build an argument list with as many file name arguments as the system supports (getconf ARG_MAX=2097152 on my system), just like xargs, and thus launch much fewer sed processes. –  Daniel Andersson Mar 29 '12 at 6:43
2  
Note to any Mac users who find this: OS X's version of sed doesn't understand the \t tab escape sequence. You can replace it with a literal tab character, which you can enter in the shell by [Ctrl]+V, [Tab]. –  Jeremy Banks Dec 17 '12 at 20:44
show 1 more comment

There are lots of ways to do this. There are also lots of ways to shoot yourself in the foot while doing this if you're not careful or if you're new to Linux as you appear to be. Assuming that you can create a list of files that you want to convert, either by using something like find or manually with an editor, just pipe that list into the following.

while read file
do
   expand "$file" > /tmp/expandtmp
   mv /tmp/expandtmp "$file"
done

One way you can shoot yourself in the foot with that is to make a typo so that you wind up mv'ing an empty file to all of the file names you specify, thereby deleting the contents of all your files. So be careful and test whatever you do first on a small set of files that you have backed up.

share|improve this answer
2  
Make the mv conditional on the success of expand: expand ... && mv ... –  Dennis Williamson Jul 2 '10 at 10:04
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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