2

I wrote a small script that will recursively go through all *.py files within a directory and replace specific entries in the files.

So the files and their current content:

find . -name "*.py" -exec ls "{}" \; -exec cat "{}" \;

and that returns this:

./1/File1.py
import sys

./2/3/File3.py
import sys
sys.exit(1)

./6/7/File7.py
import sys
sys.exit()

./File0.py
import sys

Now the script I wrote is this:

for file in $(find . -name "*.py")
do
    echo "$file"
    sed 's/sys.exit.*/os_.exit()/g;s/import sys/&\nimport os/g' "$file"
done

Now if I ran those sed commands on their own, I would get my desired output. If I run them both together within my script, or like so:

find . -name "*.py" -exec sed 's/sys.exit.*/os_.exit()/g' "{}" \; -exec sed 's/import sys/&\nimport os/g' "{}" \;

it would end up duplicating my output like this:

./1/File1.py
import sys
import sys
import os

./2/3/File3.py
import sys
os_.exit()
import sys
import os
sys.exit(1)

./6/7/File7.py
import sys
os_.exit()
import sys
import os
sys.exit()

./File0.py
import sys
import sys
import os

Can someone point out what I'm doing wrong?

EDIT: thanks to the link posted by don_crissti, I have edited the script to actually execute a 'one-liner'. I have posted this below, thanks to the input from all who commented it has resolved my issue.

find . -name "*.py" -exec ls "{}" \; -exec sed 's/sys.exit.*/os_.exit()/g;s/import sys/&\nimport os/g' "{}" \;
Rui F Ribeiro
  • 55,929
  • 26
  • 146
  • 227
64Hz
  • 79
  • 1
  • 5
  • 1
    Why don't you put both edit commands in the same `sed` invocation? – AlexP May 11 '18 at 09:52
  • I agree with @AlexP. I think that will also solve the original problem. – Iskustvo May 11 '18 at 09:53
  • Good plan, will edit. – 64Hz May 11 '18 at 09:54
  • [Don't loop over find's output.](https://unix.stackexchange.com/q/321697/22142). Other than that your script behaves as expected (that is, `sed` _autoprints_ all lines, even if no changes were made) – don_crissti May 11 '18 at 09:54
  • I noticed that as I hit save. Have fixed it now, thanks. Adding them into the one `sed` invocation has corrected my issue. How would you recommend a loop over all *.py files to perform these edits in that case? – 64Hz May 11 '18 at 09:56
  • Note that you don't actually edit *the files*. The `sed` commands as written read a file and output the edited text. If you want to edit the files you need `sed -i`. – AlexP May 11 '18 at 09:57
  • 1
    Sorry @AlexP, I meant to add that my script was to test the output before I actually edit them. I will add `-i` when I am confident it will output correctly. – 64Hz May 11 '18 at 10:01
  • @AlexP Since you are the first to propose joining of multiple `sed`'s in one, you should post the official answer. – Iskustvo May 11 '18 at 10:18
  • @Iskustvo: OK done. – AlexP May 11 '18 at 12:15

1 Answers1

1

The output is as should be expected, because each of the two sed commands operates on the same unmodified input text. In order to obtain the output which the inquirer expected, the two substitute commands should be combined in one invocation of sed:

... -exec sed -e 's/sys.exit.*/os_.exit()/g' -e 's/import sys/&\nimport os/g' "{}" \;

or

... -exec sed 's/sys.exit.*/os_.exit()/g;s/import sys/&\nimport os/g' "{}" \;

AlexP
  • 10,217
  • 32
  • 41