13ren
13ren

Reputation: 12187

Using bash command line, how to add "import package.name.*;" to many java files?

I'm thinking of using find or grep to collect the files, and maybe sed to make the change, but what to do with the output? Or would it be better to use "argdo" in vim?

Note: this question is asking for command line solutions, not IDE's. Answers and comments suggesting IDE's will be calmly, politely and serenely flagged. :-)

Upvotes: 2

Views: 2138

Answers (7)

13ren
13ren

Reputation: 12187

I've actually starting to do it using "argdo" in vim. First of all, set the args:

:args **/*.java

The "**" traverses all the subdir, and the "args" sets them to be the arg list (as if you started vim with all those files in as arguments to vim, eg: vim package1/One.java package1/Two.java package2/One.java)

Then fiddle with whatever commands I need to make the transform I want, eg:

:/^package.*$/s/$/\rimport package.name.*;/

The "/^package.*$/" acts as an address for the ordinary "s///" substitution that follows it; the "/$/" matches the end of the package's line; the "\r" is to get a newline.

Now I can automate this over all files, with argdo. I hit ":", then uparrow to get the above line, then insert "argdo " so it becomes:

:argdo /^package.*$/s/$/\rimport package.name.*;/

This "argdo" applies that transform to each file in the argument list.

What is really nice about this solution is that it isn't dangerous: it hasn't actually changed the files yet, but I can look at them to confirm it did what I wanted. I can undo on specific files, or I can exit if I don't like what it's done (BTW: I've mapped ^n and ^p to :n and :N so I can scoot quickly through the files). Now, I commit them with ":wa" - "write all" files.

:wa

At this point, I can still undo specific files, or finesse them as needed.

This same approach can be used for other refactorings (e.g. change a method signature and calls to it, in many files).


BTW: This is clumsy: "s/$/\rtext/"... There must be a better way to append text from vim's commandline...

Upvotes: 0

chrio
chrio

Reputation:

You may also use the ed command to do in-file search and replace:

# delete all lines matching foobar 
ed -s test.txt <<< $'g/foobar/d\nw' 

see: http://bash-hackers.org/wiki/doku.php?id=howto:edit-ed

Upvotes: 1

Justin Scheiner
Justin Scheiner

Reputation: 280

for i in `ls *java`
do 
  sed -i '.old' '1 i\
  Your include statement here.
  ' $i
done

Should do it. -i does an in place replacement and .old saves the old file just in case something goes wrong. Replace the iterator *java as necessary (maybe 'find . | grep java' or something instead.)

Upvotes: 1

ojblass
ojblass

Reputation: 21620

I am huge fan of the following

export MYLIST=`find . -type f -name *.java`
for a in $MYLIST; do
   mv $a $a.orig
   echo "import.stuff" >> $a
   cat $a.orig >> $a
   chmod 755 $a 
done;

mv is evil and eventually this will get you. But I use this same construct for a lot of things and it is my utility knife of choice.

Update: This method also backs up the files which you should do using any method. In addition it does not use anything but the shell's features. You don't have to jog your memory about tools you don't use often. It is simple enough to teach a monkey (and believe me I have) to do. And you are generally wise enough to just throw it away because it took four seconds to write.

Upvotes: 2

cd1
cd1

Reputation: 16534

you can use sed to insert a line before the first line of the file:

sed -ie "1i import package.name.*;" YourClass.java

use a for loop to iterate through all your files and run this expression on them. but be careful if you have packages, because the import statements must be after the package declaration. you can use a more complex sed expression, if that's the case.

Upvotes: 1

D.Shawley
D.Shawley

Reputation: 59583

I would use sed if there was a decent way to so "do this for the first line only" but I don't know of one off of the top of my head. Why not use perl instead. Something like:

find . -name '*.java' -exec perl -p -i.bak -e '
    BEGIN {
      print "import package.name.*;\n"
    }' {} \;

should do the job. Check perlrun(1) for more details.

Upvotes: 1

chaos
chaos

Reputation: 124325

I'd suggest sed -i to obviate the need to worry about the output. Since you don't specify your platform, check your man pages; the semantics of sed -i vary from Linux to BSD.

Upvotes: 1

Related Questions