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' "{}" \;
9
  • 1
    Why don't you put both edit commands in the same sed invocation?
    – AlexP
    May 11 '18 at 9:52
  • I agree with @AlexP. I think that will also solve the original problem.
    – Iskustvo
    May 11 '18 at 9:53
  • Good plan, will edit.
    – 64Hz
    May 11 '18 at 9:54
  • Don't loop over find's output.. Other than that your script behaves as expected (that is, sed autoprints all lines, even if no changes were made) May 11 '18 at 9:54
  • 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
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' "{}" \;

1
  • Thank you for the explanation and fix! Much appreciated.
    – 64Hz
    May 11 '18 at 12:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.