login
Header Space

 
 

Re: find -exec {} help

Previous thread: New Asus MB dmesg with new snapshot by Sam Fourman Jr. on Monday, June 4, 2007 - 2:01 am. (1 message)

Next thread: OpenBSD T-Shirt needed by Daniel on Monday, June 4, 2007 - 3:15 am. (1 message)
To: <misc@...>
Date: Monday, June 4, 2007 - 3:04 am

hi, I'm using 3.8, and I hate to bother, but I have spent two days on the 
net trying to find the answer to this problem.

I am using 'find' to batch file a sed search and replace.  Sed, of course, 
outputs to stdout, the problem I am having is finding the correct syntax so 
that I can change the extension of the input file to create the new output 
file.  For example:

so if the input file happens to be smith.htm, then '{}' would be smith.htm 
and the idea is that the output filename for the sed command would create a 
new output file called smith.htm.new.

this of course isn't working.

any help please? thanks.

david
incomex@hotmail.com

_________________________________________________________________
PC Magazines 2007 editors choice for best Web mailaward-winning Windows 
Live Hotmail. 
http://imagine-windowslive.com/hotmail/?locale=en-us&amp;ocid=TXT_TAGHM_migration_HM_m...
To: David B. <incomex@...>
Cc: <misc@...>
Date: Monday, June 4, 2007 - 5:35 am

you pass {} to the shell as part of the filename to redirect the
output from find(1) to, it is not seen by find(1) at all (and you
don't pass the filename to sed, either).

if you want to redirect via -exec you can do it like this:

$ find . -name '*.htm' -exec sh -c 'sed s/old/new/ &lt; {} &gt; {}.new' \; 

but do you know about the simpler perl options for in-place editing?
see perlrun(1) about the -i option, here are the more common forms:

$ perl -pi.orig -e 's,foo,bar,' *.htm
(with backup)

$ perl -pi -e 's,foo,bar,' *.htm
(without)
To: David B. <incomex@...>
Cc: <misc@...>
Date: Monday, June 4, 2007 - 4:14 am

&gt; Find . -name "*.htm" -exec 'sed s/old/new/' &gt; '{}'.new


the above command is probably a sytnax error, due to unterminated
-exec (add \; at the end to fix this), that apart that command should
look for a command 'sed s/old/new/' (note: it should NOT invoke sed
command with s/old/new/ argument).


find . -name "*.htm" -exec echo '{}.new' \;

should do what you want.



-- 
almir
To: David B. <incomex@...>
Cc: <misc@...>
Date: Monday, June 4, 2007 - 3:30 am

I'd probably use a for loop.

*untested*
for i in *.html ; do mv $i `echo $i | sed 's/\(.*\.\)html/\1html.new/'` ; done

--Bryan
To: <root@...>
Cc: David B. <incomex@...>, <misc@...>
Date: Monday, June 4, 2007 - 8:01 am

Don't use for loops with find results, they do not scale well.
Also, beware of spaces in file.

For this kind of thing, I generally use 'while read'

find . -type f -name \*.htm -print|while read f; do sed s/old/new &lt;"$f" &gt;"$f.new"; done
To: Misc OpenBSD <misc@...>
Date: Monday, June 4, 2007 - 9:26 am

Use xargs(1)

Best
   Martin
To: Misc OpenBSD <misc@...>
Date: Monday, June 4, 2007 - 11:28 am

Hello!


For that case, it doesn't really help, because the filename is needed in
a redirection. And if you need the filename in more arguments, xargs is
a bit silly too, because it *has* the option -I, but that has the
completely arbitrary limitation of 255 characters which can't be changed

Kind regards,

Hannah.
To: <root@...>, David B. <incomex@...>, <misc@...>
Date: Monday, June 4, 2007 - 8:25 am

Hello!


This isn't safe wrt newlines in file names, either.

A completely safe solution would be writing a small script:

#! /bin/sh
exec sed s/old/new/ &lt; "$1" &gt; "$1".new

and using find . -type f -name \*.htm -exec /path/to/script {} \;
or find . -type f -name \*.htm -print0 | xargs -0 -L 1 -r /path/to/script

Kind regards,

Hannah.
To: <root@...>, David B. <incomex@...>, <misc@...>
Date: Monday, June 4, 2007 - 4:46 pm

newlines in file names are a pretty infrequent occurrence.

In case this could happen, I would do it in perl and get rid of the sed 
entirely.

#! /usr/bin/perl
use File::Find;

sub
transform
{
	my $filename = shift;
	open my $fh, '&lt;', $filename or 
		die "Problem with $filename: $!\n";
	open my $fh2, '&gt;', "$filename.new" or
		die "Problem with $filename.new: $!\n";
	while (&lt;$fh&gt;) {
		s/old/new/;
		print $fh2 $_
	}
}

find(sub {
	return unless -f $_;
	return unless m/\.htm$/;
	transform($_);
}, '.');

or something like this...
To: <misc@...>
Date: Monday, June 4, 2007 - 12:54 pm

I think this is also correct:

find . -name '*.htm' -exec cp '{}' '{}'.new \; \
-exec sed -i s/old/new/ '{}'.new \;
To: Tom Van Looy <tom@...>
Cc: <misc@...>
Date: Monday, June 4, 2007 - 4:30 pm

Hi!


I don't see any -i option documented in the sed manpage.

Kind regards,

Hannah.
To: Tom Van Looy <tom@...>, <misc@...>
Date: Monday, June 4, 2007 - 5:37 pm

I believe the -i option is only available in gnu sed. It stands for
"in-place" which means it modifies the original file. You can specify an
extension for a backup file to preserve the original content.


Terry
To: terry tyson <beebum@...>
Cc: Tom Van Looy <tom@...>, <misc@...>
Date: Monday, June 4, 2007 - 6:04 pm

Hello!


May be. But this is misc@*OpenBSD* and not
misc@some-system-where-sed-means-gnu-sed

Kind regards,

Hannah.
To: <root@...>, David B. <incomex@...>, <misc@...>
Date: Monday, June 4, 2007 - 12:27 pm

...-exec sh -c 'something with $1' {} \; is fully safe as well.


-- 
almir
To: <misc@...>
Date: Monday, June 4, 2007 - 12:58 pm

Hello!


sh -c 'echo foo"$1"bar' baz

-&gt; foobar

Seems not.

Kind regards,

Hannah.
To: <misc@...>
Date: Monday, June 4, 2007 - 1:49 pm

a typo, sorry, it should be sh -c 'echo foo$1bar' -- baz


i am cheating tho, and have sh symlinked to bash.



-- 
almir
To: Almir Karic <redduck666@...>
Cc: <misc@...>
Date: Monday, June 4, 2007 - 4:32 pm

Hi!


This works indeed. But better use the additional quotes around $1. Just

Why?

Better don't do that.

Kind regards,

Hannah.
To: Almir Karic <redduck666@...>, <misc@...>
Date: Monday, June 4, 2007 - 5:45 pm

i learnt to use bash, and posix sh is not good enaugh any more. tho to
be fair, most of the features i like in bash are (probably)
implemented in ksh and zsh as well, i just never bothered to learn

-i on some seds (gsed, ssed, FBSD sed, maybe others) means ''in
safe temp file, so doesn't overwrite any file accidentally). but it
doesn't exists in OBSD sed, so his answer was 'wrong'.


-- 
almir
To: Almir Karic <redduck666@...>
Cc: <misc@...>
Date: Monday, June 4, 2007 - 6:21 pm

Hello!


Proactive security also means using safe patterns not only when you can

I have never missed a shell feature unless I would use awk/perl/...

It is. I'd guess it isn't in POSIX (or Single Unix) sed either, so if
you give any damn on portability, I wouldn't use it.

And then, mv doesn't know a -g flag.

Kind regards,

Hannah.
To: Almir Karic <redduck666@...>
Cc: <misc@...>
Date: Monday, June 4, 2007 - 6:19 pm

What is mv -g ? doesn't seem to be any standard option I know about ?
To: <espie@...>, Almir Karic <redduck666@...>, <misc@...>
Date: Tuesday, June 5, 2007 - 2:20 am

me feels like an idiot :/, i meant mv -f and not mv -g :/
-- 
almir
To: <misc@...>
Date: Monday, June 4, 2007 - 3:24 am

Here's a solution with sh+find+sed:

for file in $(find . -name "*.htm"); do sed 's/old/new/' $file &gt; $file.new; done

-- 
Antti Harri
Previous thread: New Asus MB dmesg with new snapshot by Sam Fourman Jr. on Monday, June 4, 2007 - 2:01 am. (1 message)

Next thread: OpenBSD T-Shirt needed by Daniel on Monday, June 4, 2007 - 3:15 am. (1 message)
speck-geostationary