Command line: search and replace in all filenames matched by grep
Do you mean search and replace a string in all files matched by grep?
perl -p -i -e 's/oldstring/newstring/g' `grep -ril searchpattern *`
Edit
Since this seems to be a fairly popular question thought I'd update.
Nowadays I mostly use ack-grep
as it's more user-friendly. So the above command would be:
perl -p -i -e 's/old/new/g' `ack -l searchpattern`
To handle whitespace in file names you can run:
ack --print0 -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g'
you can do more with ack-grep
. Say you want to restrict the search to HTML files only:
ack --print0 --html -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g'
And if white space is not an issue it's even shorter:
perl -p -i -e 's/old/new/g' `ack -l --html searchpattern`
perl -p -i -e 's/old/new/g' `ack -f --html` # will match all html files
Find and Replace string in all files recursive using grep and sed
As @Didier said, you can change your delimiter to something other than /
:
grep -rl $oldstring /path/to/folder | xargs sed -i s@$oldstring@$newstring@g
How to replace a string in multiple files in linux command line
cd /path/to/your/folder
sed -i 's/foo/bar/g' *
Occurrences of "foo" will be replaced with "bar".
On BSD systems like macOS, you need to provide a backup extension like -i '.bak'
or else "risk corruption or partial content" per the manpage.
cd /path/to/your/folder
sed -i '.bak' 's/foo/bar/g' *
How can I grep/sed taking find/replace pairs from a file?
You can make a file with a list of sed
commands like this in a file called commands.sed
:
s|cat|cats|g
s|dog|dogs|g
s|person|people|g
and run it on some input with:
echo "House mouse cat dog person dog person" | sed -f commands.sed
and it will replace cat
with cats
, dog
with dogs
and person
with people
producing:
House mouse cats dogs people dogs people
So we want to turn your file with substitutions into a command file like that - using sed
! So, if your replacements file subs.txt
contains lines like this with the two words on each line separated by a TAB:
cat cats
dog dogs
person people
That would be:
sed -e 's/^/s|/' -e $'s/\t/|/' -e 's/$/|g/' subs.txt > commands.sed
and then you can apply it with:
sed -f commands.sed SomeFile
Rather than creating a file with the commands in, we can run a process substitution
like this to dynamically generate them, and do it all in one go with:
echo "House mouse cat dog person dog person" | sed -f <(sed -e 's/^/s|/' -e $'s/\t/|/' -e 's/$/|g/' subs.txt)
Find and replace filename recursively in a directory
You can do it this way:
find . -name '123_*.txt' -type f -exec sh -c '
for f; do
mv "$f" "${f%/*}/${f##*/123_}"
done' sh {} +
No pipes, no reads, no chance of breaking on malformed filenames, no non-standard tools or features.
Best way to do a find/replace in several files?
find . -type f -print0 | xargs -0 -n 1 sed -i -e 's/from/to/g'
The first part of that is a find command to find the files you want to change. You may need to modify that appropriately. The xargs
command takes every file the find found and applies the sed
command to it. The sed
command takes every instance of from and replaces it with to. That's a standard regular expression, so modify it as you need.
If you are using svn beware. Your .svn-directories will be search and replaced as well. You have to exclude those, e.g., like this:
find . ! -regex ".*[/]\.svn[/]?.*" -type f -print0 | xargs -0 -n 1 sed -i -e 's/from/to/g'
or
find . -name .svn -prune -o -type f -print0 | xargs -0 -n 1 sed -i -e 's/from/to/g'
How to find all files containing specific text (string) on Linux
Do the following:
grep -rnw '/path/to/somewhere/' -e 'pattern'
-r
or-R
is recursive,-n
is line number, and-w
stands for match the whole word.-l
(lower-case L) can be added to just give the file name of matching files.-e
is the pattern used during the search
Along with these, --exclude
, --include
, --exclude-dir
flags could be used for efficient searching:
- This will only search through those files which have .c or .h extensions:
grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
- This will exclude searching all the files ending with .o extension:
grep --exclude=\*.o -rnw '/path/to/somewhere/' -e "pattern"
- For directories it's possible to exclude one or more directories using the
--exclude-dir
parameter. For example, this will exclude the dirs dir1/, dir2/ and all of them matching *.dst/:
grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/somewhere/' -e "pattern"
This works very well for me, to achieve almost the same purpose like yours.
For more options, see man grep
.
Using grep and sed to find and replace a string
You can use find
and -exec
directly into sed
rather than first locating oldstr
with grep
. It's maybe a bit less efficient, but that might not be important. This way, the sed
replacement is executed over all files listed by find
, but if oldstr
isn't there it obviously won't operate on it.
find /path -type f -exec sed -i 's/oldstr/newstr/g' {} \;
Ensuring grep matches from multiple files are on their own line
How about (using your method of parsing):
STRING=$(
for FILE in "${FILENAMES[@]}"; do
grep "find a line with data1 and data2" "$FILE" | sed -rn "s/(data1).*(data2).*/\1/p"
done
)
or if there are not too many files:
STRING=$(grep -h "find a line with data1 and data2" "${FILENAMES[@]}" | sed -rn "s/(data1).*(data2).*/\1/p")
==> Given your script, I am assuming <---- File1
and such is no part of the output format..
Related Topics
Http Post and Get Using Curl in Linux
Execute Combine Multiple Linux Commands in One Line
Truncating a File While It's Being Used (Linux)
How to Undo Strip - I.E. Add Symbols Back to Stripped Binary
How to Show a Gui Message Box from a Bash Script in Linux
Need to Remove the Count from the Output When Using "Uniq -C" Command
Bash Script to Remove 'X' Amount of Characters the End of Multiple Filenames in a Directory
Receiving Key Press and Key Release Events in Linux Terminal Applications
How to Reference Files Relative to Application Root in Node.Js
X86_64 Assembly Linux System Call Confusion
Can Docker Solve a Problem of Mismatched C Shared Libraries
How to Modify the Source of Buildroot Packages for Package Development
Write a Bash Shell Script That Consumes a Constant Amount of Ram for a User Defined Time
How to Convert Linux 32-Bit Gcc Inline Assembly to 64-Bit Code
Variable in Bash Script That Keeps It Value from the Last Time Running