Re: replacing text in many files

From: Chris F.A. Johnson (c.f.a.johnson_at_rogers.com)
Date: 09/15/03


Date: 15 Sep 2003 17:59:39 GMT

On Mon, 15 Sep 2003 at 17:35 GMT, Mike wrote:
> In article <bk4t0d$p95hi$1@ID-136730.news.uni-berlin.de>, Chris Johnson wrote:
>> On Mon, 15 Sep 2003 at 12:19 GMT, Martin wrote:
>>>> for f in *; do
>>>> sed "s|/usr/local/bin|usr/local|g" $f > TEMPFILE
>>>> mv TEMPFILE $f
>>>> done
>>>
>>> Btw. Can sed return a value if a match is found?
>>>
>>> The way the script works now it mv all files, even those that haven't had
>>> their content changed.
>>>
>>> So if sed could return a value, I could out the "mv TEMPFILE
>>> $f" in an if statement.
>>
>> In bash, you can also do it without sed (or any other external
>> commands):
>>
>> for f in *; do
>> x=`< "$f"` ## read the file into a variable
>> case $x in
>> */usr/local/bin*) ## make changes only if file contains /usr/local/bin
>> echo "${x//\/usr\/local\/bin/\/usr\/local}" > "$f"
>> ;;
>> esac
>> done
>>
>> This might be slower than using sed; I haven't timed it.
>>
>
> In the OP's for loop use && to prevent from messing up files.
>
> for f in *; do
> sed 's,/usr/local/bin,usr/local,g' $f > TEMPFILE && mv TEMPFILE $f
> done

    The return code from sed will be 0 unless there is an error. Not
    making any substitutions is not an error, so every file will still
    be moved.

    This would work:

cmp "$f" TEMPFILE && mv TEMPFILE "$f"

    Or compare sizes:

stat -c "%s" "$f" TEMPFILE | {
  read f1
  read f2
  [ $f1 -ne $f2 ] && mv TEMPFILE "$f"
}

-- 
	Chris F.A. Johnson
	=================================================================
	cfaj@freeshell.org                      http://cfaj.freeshell.org