Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to directly overwrite with 'unexpand' (spaces-to-tabs conversion)?

I'm trying to use something along the lines of

unexpand -t 4 *.php

but am unsure how to write this command to do what I want.

Weirdly,

unexpand -t 4 file.php > file.php

gives me an empty file. (i.e. overwriting file.php with nothing)

I can specify multiple files okay, but don't know how to then overwrite each file.

I could use my IDE, but there are ~67000 instances of to be replaced over 200 files, and this will take a while.

I expect that the answers to my question(s) will be standard unix fare, but I'm still learning...

like image 748
jezmck Avatar asked Jul 07 '09 11:07

jezmck


2 Answers

You can very seldom use output redirection to replace the input. Replacing works with commands that support it internally (since they then do the basic steps themselves). From the shell level, it's far better to work in two steps, like so:

  1. Do the operation on foo, creating foo.tmp
  2. Move (rename) foo.tmp to foo, overwriting the original

This will be fast. It will require a bit more disk space, but if you do both steps before continuing to the next file, you will only need as much extra space as the largest single file, this should not be a problem.

Sketch script:

for a in *.php
do
  unexpand -t 4 $a >$a-notab
  mv $a-notab $a
done

You could do better (error-checking, and so on), but that is the basic outline.

like image 118
unwind Avatar answered Oct 06 '22 06:10

unwind


Here's the command I used:

for p in $(find . -iname "*.js")
do
    unexpand -t 4 $(dirname $p)/"$(basename $p)" > $(dirname $p)/"$(basename $p)-tab"
    mv $(dirname $p)/"$(basename $p)-tab" $(dirname $p)/"$(basename $p)"
done

This version changes all files within the directory hierarchy rooted at the current working directory.

In my case, I only wanted to make this change to .js files; you can omit the iname clause from find if you wish, or use different args to cast your net differently.

My version wraps filenames in quotes, but it doesn't use quotes around 'interesting' directory names that appear in the paths of matching files.

To get it all on one line, add a semi after lines 1, 3, & 4.

This is potentially dangerous, so make a backup or use git before running the command. If you're using git, you can verify that only whitespace was changed with git diff -w.

like image 29
Tom Avatar answered Oct 06 '22 07:10

Tom