Find and replace with sed in directory and sub directories

320,700

Solution 1

Your find should look like that to avoid sending directory names to sed:

find ./ -type f -exec sed -i -e 's/apple/orange/g' {} \;

Solution 2

For larger s&r tasks it's better and faster to use grep and xargs, so, for example;

grep -rl 'apples' /dir_to_search_under | xargs sed -i 's/apples/oranges/g'

Solution 3

Since there are also macOS folks reading this one (as I did), the following code worked for me (on 10.14)

egrep -rl '<pattern>' <dir> | xargs -I@ sed -i '' 's/<arg1>/<arg2>/g' @

All other answers using -i and -e do not work on macOS.

Source

Solution 4

This worked for me:

find ./ -type f -exec sed -i '' 's#NEEDLE#REPLACEMENT#' *.php {} \;

Solution 5

grep -e apple your_site_root/**/*.* -s -l | xargs sed -i "" "s|apple|orage|"
Share:
320,700

Related videos on Youtube

hd.
Author by

hd.

Updated on July 08, 2022

Comments

  • hd.
    hd. almost 2 years

    I run this command to find and replace all occurrences of 'apple' with 'orange' in all files in root of my site:

    find ./ -exec sed -i 's/apple/orange/g' {} \;
    

    But it doesn't go through sub directories.

    What is wrong with this command?

    Here are some lines of output of find ./:

    ./index.php
    ./header.php
    ./fpd
    ./fpd/font
    ./fpd/font/desktop.ini
    ./fpd/font/courier.php
    ./fpd/font/symbol.php
    
    • Jacob
      Jacob almost 13 years
      could you run find ./ and post some sample output? And the directory strucuture please. edit: thanks!
    • Jacob
      Jacob almost 13 years
      Hm your find is correct, works for me with subdirs.
    • carlpett
      carlpett almost 13 years
      How do you know it does not process subdirectories?
    • hd.
      hd. almost 13 years
      because it gives these errors: sed: couldn't edit ./fpd: not a regular file sed: couldn't edit ./fpd/font: not a regular file sed: couldn't edit ./fpd/font/makefont: not a regula
    • hd.
      hd. almost 13 years
      oh... i grep for apple and nothing found.they all were replaced. ;) thank you . you opened my eyes !!!
    • tripleee
      tripleee about 8 years
    • user3167101
      user3167101 almost 8 years
      If using zsh, you can use e.g. src/**/.js.
    • Yahor M
      Yahor M about 6 years
      Answer you can find here: stackoverflow.com/a/49364510/5578292
    • tripleee
      tripleee almost 5 years
      The error messages are unnerving, but the command actually does what you want. It's not correct to say it "doesn't work", though it's legitimate and useful to ask how to do this without those warning messages.
  • paulmelnikow
    paulmelnikow over 10 years
    You may need to change sed -i 's/apple/orange/g' to sed -i '' 's/apple/orange/g' to make this work.
  • paulmelnikow
    paulmelnikow about 10 years
    -i takes an argument: the extension used to save the temporary file. In GNU sed, looks like there's no space between -i and its argument, but in BSD sed there is… so BSD -i '' 's/foo/bar/' is equivalent to GNU -i 's/foo/bar/.
  • paulmelnikow
    paulmelnikow about 10 years
    Actually adding -e does not work on Mac OS. touch a b c d e followed by the command above produces a directory listing like this: a a-e b b-e c c-e d d-e e e-e.
  • mrodrigues
    mrodrigues almost 8 years
    Thanks for this answer, it was very helpful! If in a git repository, it's even faster using git grep -l 'apples' | xargs sed -i 's/apples/oranges/g'
  • phuclv
    phuclv almost 7 years
    he wants to find all files in sub directories contain that string and replace, not only a single file
  • kakoma
    kakoma over 6 years
    For Mac OS, this answers stackoverflow.com/questions/19242275/… the RE error: illegal byte sequence
  • Kevin Cherepski
    Kevin Cherepski about 6 years
    For fish shell users, be sure to quote the empty braces '{}', because fish automatically expands the empty braces if not quoted.
  • Colin D
    Colin D about 6 years
    Is there are shorter version of this? Pretty lengthy. Or a way to make it an alias/bash function?
  • knocte
    knocte over 5 years
    original question doesn't restrict to *.php files, there's also an .ini one
  • tripleee
    tripleee almost 5 years
    The unquoted *.php is really incorrect; you just got lucky that it didn't get expanded in the starting directory because you didn't happen to have any matching files there.
  • aleric
    aleric over 3 years
    Restriction on file name could be obtained with -name *.php on the find command.
  • cacti5
    cacti5 over 3 years
    If on macos, use xargs sed -i '' 's/apples/oranges/g'
  • quantum231
    quantum231 over 2 years
    Can someone please explain what is the -exec and the {} \; at the end?
  • bob dylan
    bob dylan over 2 years
    On the mac the accepted answer does work [kind of] - but it spits out 'duplicate' files with <original-filename>-e which would need to be removed / piped into another command (to use verbatim). This method is better though and is still working for me (on 11.2.3)
  • Colin D
    Colin D over 2 years
    could this be turned into a shortened alias?
  • NessDan
    NessDan about 2 years
    If you're trying to replace something with a forward slash in it, you can use sed with | rather than /, e.g. ... xargs sed -i 's|mduuid/apples|mduuid/oranges|g' stackoverflow.com/questions/40714970/…