How to get filenames when using find and sed
Solution 1
Your sed
command (with proper quoting):
sed 's/str1/str2/g'
This will change all occurrences of str1
into str2
. A list of files containing str1
can be had from grep -l 'str1'
:
find . -type f \( -name '*.txt' -o -name '*.git' \) \
-exec grep -l 'str1' {} \; \
-exec sed -i 's/str1/str2/g' {} + >changelist.txt
Here, grep -l
will provide a list of pathnames that will be redirected into changelist.txt
. It will also act like a filter for sed
so that sed
is only run on files that contain the pattern. sed -i
will then make the changes in the files (and remain quiet).
Alternatively, let find
print the pathnames of the files that contain the string:
find . -type f \( -name '*.txt' -o -name '*.git' \) \
-exec grep -q 'str1' {} \; \
-print \
-exec sed -i 's/str1/str2/g' {} + >changelist.txt
Related:
Solution 2
sed -i
rewrites the file (actually makes full new copies of the files) regardless of whether any of the s
commands in the sed
script succeeded or not.
Here, you'd want to avoid running sed -i
on files that don't contain str1
. With GNU tools:
find . -type f \( -name "*.txt" -o -name "*.git" \) -size +3c \
-exec grep -lZ str1 {} + |
while IFS= read -rd '' file; do
sed -i 's/str1/str2/g' "$file" &&
printf '%s\n' "$file"
done
That runs one sed
for each of the files that contain str1
and prints the file names if sed
has been successful (for which there has been no error in creating the new version of the file).
Or you can run one grep
and sed
per file:
find . -type f \( -name "*.txt" -o -name "*.git" \) \( -size +3c \
-exec grep -q str1 {} \; \
-exec sed -i 's/str1/str2/g' {} \; \
-printf '"%p" was modified\n' \
-o -printf '"%p" was not modified\n"' \)
Related videos on Youtube
KLMM
Updated on September 18, 2022Comments
-
KLMM over 1 year
I am writing a script to apply sed on certain files and then list files that have been changed so that I know which have been modified.
This is how I am finding and then using sed:
find . -type f -a \( -name "*.txt" -o -name "*.git"\) -a -exec sed -i -e "s/"str1"/"str2"/g" {} +
How do I print the file name of the changed files? I would like to print it in a sorted order so it's easier to read.
When using only sed we can do this:
sed -i 's/$pattern/$new_pattern/w changelog.txt' $filename if [ -s changelog.txt ]; then # CHANGES MADE, DO SOME STUFF HERE else # NO CHANGES MADE, DO SOME OTHER STUFF HERE fi
But how do I do this when using find and sed together? I checked the man page and tried a bunch of stuff but nothing worked.
-
Admin over 8 yearsI'm not exactly sure what you're trying to achieve, can you show a list of files, and what output you're expecting to see.
-
Admin over 8 years@EightBitTony I have added examples, please take a look
-
Admin over 8 yearsYou just add
-print
after your-exec
, it will only be executed if the-exec
was successful e.g.find . -type f \( -name \*.git -o -name \*.txt \) -exec sed -i 'blah_blah' {} \; -print
. Sure, you'll have to sort the output then. -
Admin over 8 years@don_crissti using print giving an error "-print: command not found".
-
Admin over 8 years@don_crissti yes this worked for printing the file but how can I get them in a sorted order because we are not storing then output in any variable and there is no flag that we can use to sort. How Can i achieve sorted order?
-
Admin over 8 yearsI found that your suggestion of using print, prints all the files having the extension .txt or .git. I only want to print files that have been modified not all that match the pattern
-
Admin over 8 yearsIf you use the AST
find
you can sort its output.
-
-
terdon over 8 yearsPlease edit your answer so that it actually provides an answer. At the moment, this is a comment simply giving a suggestion.
-
KLMM over 8 years@unxnut I am unable to understand your answer, I do have a high level idea of what needs to be done. Please provide some code solution, thanks
-
KLMM over 8 years@unxnut Is it possible to achieve this in a single script(will using routines work)? And how do we get sorted order?
-
unxnut over 8 yearsSince the filenames for the session are saved in
changelog
, all you have to do issort changelog
to get the file in sorted order at the end of thefind
command.