sed beginner: changing all occurrences in a folder sed beginner: changing all occurrences in a folder shell shell

sed beginner: changing all occurrences in a folder


There is no way to do it using only sed. You'll need to use at least the find utility together:

find . -type f -exec sed -i.bak "s/foo/bar/g" {} \;

This command will create a .bak file for each changed file.

Notes:

  • The -i argument for sed command is a GNU extension, so, if you are running this command with the BSD's sed you will need to redirect the output to a new file then rename it.
  • The find utility does not implement the -exec argument in old UNIX boxes, so, you will need to use a | xargs instead.


I prefer to use find | xargs cmd over find -exec because it's easier to remember.

This example globally replaces "foo" with "bar" in .txt files at or below your current directory:

find . -type f -name "*.txt" -print0 | xargs -0 sed -i "s/foo/bar/g"

The -print0 and -0 options can be left out if your filenames do not contain funky characters such as spaces.


For portability, I don't rely on features of sed that are specific to linux or BSD. Instead I use the overwrite script from Kernighan and Pike's book on the Unix Programming Environment.

The command is then

find /the/folder -type f -exec overwrite '{}' sed 's/old/new/g' {} ';'

And the overwrite script (which I use all over the place) is

#!/bin/sh# overwrite:  copy standard input to output after EOF# (final version)# set -xcase $# in0|1)        echo 'Usage: overwrite file cmd [args]' 1>&2; exit 2esacfile=$1; shiftnew=/tmp/$$.new; old=/tmp/$$.oldtrap 'rm -f $new; exit 1' 1 2 15    # clean up filesif "$@" >$new               # collect inputthen    cp $file $old   # save original file    trap 'trap "" 1 2 15; cp $old $file     # ignore signals          rm -f $new $old; exit 1' 1 2 15   # during restore    cp $new $fileelse    echo "overwrite: $1 failed, $file unchanged" 1>&2    exit 1firm -f $new $old

The idea is that it overwrites a file only if a command succeeds. Useful in find and also where you would not want to use

sed 's/old/new/g' file > file  # THIS CODE DOES NOT WORK

because the shell truncates the file before sed can read it.