Click to See Complete Forum and Search --> : Help me writing a simple script
andrzej
07-31-2001, 07:45 PM
I'm trying to write a script that will search a dir and all its subdirs for files containing an expression and replace all occurences of that expression with a string.
So far I've this:
find /mydir -name '*' -exec sed 's/searched/new/g' '{}' \;
I'm getting a nice listing of corrected text. But how do I write the text back to files ?
This doesn't work:
... sed 's/.../.../g' '{}' | cat > '{}' \;
It's 2am here, I'm probably just tired.
Any help appreciated.
The Kooman
07-31-2001, 11:31 PM
Originally posted by andrzej:
<STRONG>
find /mydir -name '*' -exec sed 's/searched/new/g' '{}' \;
I'm getting a nice listing of corrected text. But how do I write the text back to files ?
This doesn't work:
... sed 's/.../.../g' '{}' | cat > '{}' \;
</STRONG>
The '|' in your command takes you out of the find command. The shell would interpret it as you wanting to redirect the output of your find -exec command to the command "cat > '{}'" and try to create a filename called '{}' in the directory where you started! However your exec command would still be unterminated at this point and so you'd probably get the "find: missing argument to -exec" error!
Also, even if it were syntatically permissible, you'd be reading from and writing to a file at the s
ame time ... problem!!! You should be writing to a temporary file and the renaming the file, perhaps
like this:
Warning: Untested Code
find /mydir -name '*' -exec bash -c 'sed "s/searched/new/g" "{}" > {}.tmp; mv -f {}.tmp > {}' \;
HTH
andrzej
08-01-2001, 03:51 AM
You've described exactly what I was getting. :)
More importantly your "script" worked like a charm (after one minor modification).
find /mydir -name '*' -exec bash -c 'sed "s/searched/new/g" "{}" > {}.tmp; mv -f {}.tmp {}' \;
Thank you very much. You've saved me a lot of time.
:)
The Kooman
08-02-2001, 02:12 AM
Originally posted by andrzej:
find /mydir -name '*' -exec bash -c 'sed "s/searched/new/g" "{}" > {}.tmp; mv -f {}.tmp {}' \;
Oh yeah - the ">" at the end shouldn't have been there - I was still thinking of the redirection when I wrote that!!
jemfinch
08-02-2001, 04:14 AM
This is one of the few problems that Perl is very suited for:
find /mydir |xargs perl -pi -e s/searched/new/g
Note that you don't need the "-name '*'", as that's the default, and that you'll need to quote s/searched/new/g if it contains shell metacharacters.
Perl -p wraps your script in a "while(<> ) { ... }" block, -i means "do the editing in-place, on the files themselves", and -e means "execute this" (which is wrapped in "while(<> ) { ... }" block by the -p) This is way cleaner than using temporary files and sed and stuff, and you'll get more powerful regular expressions as an added advantage.
Jeremy
[ 02 August 2001: Message edited by: jemfinch ]
andrzej
08-02-2001, 04:56 AM
I wanted quickly modify 100+ files, learning a new programming language is not what I call a quick solution. (While thinking how to do it I even opened the perl manpage, though).
Your solution is indeed beautiful. I'm adding it to my small-scripts-and-hacks-for-any-occassion directory.
Thanks !
jemfinch
08-02-2001, 05:23 AM
Originally posted by andrzej:
I wanted quickly modify 100+ files, learning a new programming language is not what I call a quick solution. (While thinking how to do it I even opened the perl manpage, though).
Heck, to use "perl -pi -e" doesn't require learning a new language, just a different (far more powerful) regular expression engine. I didn't post because you needed an answer (you'd already found one, and I knew it :)) I posted it because next time this'll be a better solution for you :)
Your solution is indeed beautiful. I'm adding it to my small-scripts-and-hacks-for-any-occassion directory.
Exactly. That was my goal :)
Jeremy