2

For those who are curious as to why I'm doing this: I need specific files in a tar ball - no more, no less. I have to write unit tests for make check, but since I'm constrained to having "no more" files, I have to write the check within the make check. In this way, I have to write bash(but I don't want to).

I dislike using bash for unit testing(sorry to all those who like bash. I just dislike it so much that I would rather go with an extremely hacky approach than to write many lines of bash code), so I wrote a python file. I later learned that I have to use bash because of some unknown strict rule. I figured that there was a way to cache the entire content of the python file into a single string in the bash file, so I could take the string literal in bash and write to a python file and then execute it.

I tried the following attempt (in the following script and result, I used another python file that's not unit_test.py, so don't worry if it doesn't actually look like a unit test):

toStr.py:

import re

with open("unit_test.py", 'r+') as f:
    s = f.read()

s = s.replace("\n", "\\n")
print(s)

And then I piped the results out using:

python toStr.py > temp.txt

It looked something like:

#!/usr/bin/env python\n\nimport os\nimport sys\n\n#create number of bytes as specified in the args:\nif len(sys.argv) != 3:\n print("We need a correct number of args : 2 [NUM_BYTES][FILE_NAME].")\n exit(1)\nn = -1\ntry:\n n = int(sys.argv[1])\nexcept:\n print("Error casting number : " + sys.argv[1])\n exit(1)\n\nrand_string = os.urandom(n)\n\nwith open(sys.argv[2], 'wb+') as f:\n f.write(rand_string)\n f.flush()\n f.close()\n\n

I tried taking this as a string literal and echoing it into a new file and see whether I could run it as a python file but it failed.

echo '{insert that giant string above here}' > new_unit_test.py

I wanted to take this statement above and copy it into my "bash unit test" file so I can just execute the python file within the bash script.

The resulting file looked exactly like {insert giant string here}. What am I doing wrong in my attempt? Are there other, much easier ways where I can hold a python file as a string literal in a bash script?

Community
  • 1
  • 1
OneRaynyDay
  • 3,658
  • 2
  • 23
  • 56
  • it definately seems like whatever you want to do this is probably not the best way to do it... – Joran Beasley Sep 27 '16 at 06:11
  • You are correct sir! And therefore I am inquiring on what other easy methods I have to "use bash" but not actually use bash. – OneRaynyDay Sep 27 '16 at 06:12
  • why do you have to "use bash" ? – Joran Beasley Sep 27 '16 at 06:18
  • Answered in the post - Have to do some makefile stuff. – OneRaynyDay Sep 27 '16 at 06:19
  • then use `os.system` from within python ... or better yet `subprocess` module ... to just run the makefile thing ... also python has a `tar` package builtin ...https://docs.python.org/2/library/tarfile.html – Joran Beasley Sep 27 '16 at 06:20
  • 1
    But the strict specifications say that Makefile has to be present. And it has to be a makefile. I can't have a physical python file in the tar ball. I do have subprocess modules running bash within my python script but I guess that's beside the point. The interface is that they will call `make check`. – OneRaynyDay Sep 27 '16 at 06:22

1 Answers1

3

the easiest way is to only use double-quotes in your python code, then, in your bash script, wrap all of your python code in one pair of single-quotes, e.g.,

#!/bin/bash

python -c 'import os
import sys

#create number of bytes as specified in the args:
if len(sys.argv) != 3:
    print("We need a correct number of args : 2 [NUM_BYTES][FILE_NAME].")
    exit(1)

n = -1
try:
    n = int(sys.argv[1])
except:
    print("Error casting number : " + sys.argv[1])
    exit(1)

rand_string = os.urandom(n)

# i changed ""s to ''s below -webb
with open(sys.argv[2], "wb+") as f:
    f.write(rand_string)
    f.flush()
    f.close()'
webb
  • 4,180
  • 1
  • 17
  • 26
  • im gessing he wants `{some_custom_stuff}` somewhere also ... +1 though – Joran Beasley Sep 27 '16 at 06:16
  • Huh - interesting. Thanks for the suggestion! I'll try that right now. EDIT: I don't think I can do this. I'm using a makefile that treats tabbed line-by-line executions. I think there might be a way to join the two lines with a '/' or something. – OneRaynyDay Sep 27 '16 at 06:17
  • Yep - having some trouble trying to execute the makefile. It says this error message: `Makefile:2: *** missing separator. Stop.` Due to the fact that it can't take multi-line arguments. – OneRaynyDay Sep 27 '16 at 06:30
  • 1
    oh, i didn't notice that it's in a makefile. this might help: https://stackoverflow.com/questions/10121182/multiline-bash-commands-in-makefile – webb Sep 27 '16 at 06:34
  • 1
    After 40 minutes of struggles I have finally done it. Thank you sir! As a future note: You can't use the \ without ending the quote. Therefore, I couldn't directly call the python code. I echo'd the string into a file and then executed python from there. It worked. – OneRaynyDay Sep 27 '16 at 07:13
  • great! please append the code that worked to the bottom your question above for future people. – webb Sep 27 '16 at 16:08