Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Help with shell scripting

Name: Anonymous 2010-09-24 18:59

I'm taking a Unix class and we're supposed to write two scripts
The first one looks up every .c and .cc file in the current directory for the strings "printf" and "fprintf". If either string is found, the script adds "#include <stdio.h>" to the beginning of the file unless it's already been included.

The second compares two directories dir1 and dir2 (supplied as arguments) and copies and overwrites to dir1 from dir2 every file that is not present in dir1 or newer than its namesake in dir1.

I'm trying to write the first one right now, and I think I'm close, but I'm getting an error. I'm really new to shell scripting and *nix in general.

http://pastebin.com/RHmTdjYw

Name: Anonymous 2010-09-24 19:15



#!/bin/sh

for file in `ls *.c{,c}`
do
    if grep 'printf' $file ;    then
        if ! grep '#include <stdio.h>' $file ; then
            mv "$file" "$file~"
            ( echo '#include <stdio.h>'; cat "$file~" ) > "$file"
        fi
    fi
done



I HELPED HIM

I dont know how to sed ..read the man to do the sed -i business

Name: Anonymous 2010-09-24 19:15

oh you need to sort out that first regex as well

Name: Anonymous 2010-09-24 19:19

also you dont really need the ls  ..you can do for file in *.c *.cc as wildcard expansion is done by the shell

Name: Anonymous 2010-09-24 19:55

>>2
Thanks man. I've got it working perfectly now. I looked up the man page for sed so I'm using sed to do the editing. Would you mind telling me why exactly my first script wasn't working? I'm actually trying to learn this stuff, but it's pretty intimidating.

>>4
Oh weird, I wouldn't have thought that would work. Thanks though, that's more human readable than what what I had.

Name: Anonymous 2010-09-24 20:00

>>5
the [ is a special if subset for testing certain things... for testing the exit status of commands you don't need it...   in fact [ is effectivly a command that returns an exit status reflecting the expression inside the []

Name: Anonymous 2010-09-24 20:02

>>5
also some worth mentioning is to ensure your regex doesnt match for other members of the printf family (eg sprinf), otherwise you will erronously add stdio.h

Name: Anonymous 2010-09-24 20:12

>>7
What would be the best way to do that?

Name: Anonymous 2010-09-24 20:19

>>8
Well, either it can be done with some expert regex, or maybe a grep -v in the first if

Name: Anonymous 2010-09-24 20:26

>>7
>>8
>>9
I think I got it: grep -E '\<(printf|fprintf)'
The \< limits the match to the beginning of a word, so it won't match sprintf and the like.

Name: Anonymous 2010-09-24 21:14

in b4 1-line Perl solution

Name: Anonymous 2010-09-24 21:32

>>11
Made me smile. I still don't know how to do this off-hand in (one line of) Perl 6.

Perl 5 (or even Python) wouldn't be a bad choice though, developers worldwide have been bitching lately about the futility of writing portable shell scripts, but you can't have a working Unix without Perl and often Python installed these days.

Name: Anonymous 2010-09-25 9:01

>>10
OMG OPTIMISED REGEX
\<f?printf

>>11
Your wish is my command.
grep{open(F,$_),($d=((grep{/\bf?printf/}@l=<F>)&&!(grep{/#include <stdio\.h>/}@l))),close(F),$d?do{open(F,">$_"),print(F "#include <stdio.h>\n"),print(F @l),close(F)}:0}glob"*.c *.cc";

Python pig disgusting
Perl pig delicious

Name: 13 2010-09-25 9:04

>>1
Second part:
#!/bin/sh
cp -uR "$2" "$1"


also lol bampu pantsu

Name: Anonymous 2010-09-25 9:58

=:!^#include <stdio\.h>!,~&.'printf'<h//0+fo|'*.{c,cc}'x

Name: Anonymous 2010-09-25 12:01

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;

public class Prog {
  public static void main(String[] args) {
    try {
      File dir = new File(System.getProperty("user.dir"));
      for (String file : dir.list(
          new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
              return name.matches(".*\\.cc?$");
            }
          })) {
        Process grep = Runtime.getRuntime().exec(new String[] {"/usr/bin/grep", "-E", "\\bf?printf", file});
        int returnValue = grep.waitFor();
        if (returnValue == 0) {
          Process grep2 = Runtime.getRuntime().exec(new String[] {"/usr/bin/grep", "^#include <stdio.h>", file});
          int returnValue2 = grep2.waitFor();
          if (returnValue2 == 1) {
            FileInputStream stream = new FileInputStream(file);
            String newBuf;
            try {
              FileChannel fc = stream.getChannel();
              MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
              newBuf = "#include <stdlib.h>\n" + Charset.defaultCharset().decode(bb).toString();
            }
            finally {
              stream.close();
            }

            FileOutputStream ostream = new FileOutputStream(file);
            try {
              FileChannel fc = ostream.getChannel();
              fc.write(Charset.defaultCharset().encode(newBuf));
            } finally {
              ostream.close();
            }
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

Name: Anonymous 2010-09-25 20:00

>>13
I took one look at that and felt nauseous. (I only skimmed it, but don't you have one too many greps in there?) Then I banged out a Perl 6 version which was immediately unreadable to me. No other language has tricked me into relying on nested closures so much (it had the form: for grep {...}, (for grep {...}, (for() {...}) {...} ) {...} roughly, and read each file up to 3 times.)

Name: Anonymous 2010-09-26 10:39

>>17
Thank you. It warms my heart (penis) to hear of those who regurgitate lunch upon viewing my Perl code.

I suppose could replace the outermost grep with a map, or even
/grep{(.*)}(glob"*.c");/
with
\1 for\2, is that what you're getting at?

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List