0

I have a py script which gets as an argument data stream char > and >>, for example

python script.py -o 'ls -la /tmp > /tmp/test'

When I'm executing this kind of command the > char perceived with my terminal. Could you help me, how can I pass the > as a symbol so that my console doesn't think of it as a command?

Cyrus
  • 84,225
  • 14
  • 89
  • 153
  • 1
    Single quotes, as you use, should work. If you need to pass separate args, then you can quote just `>` as: `python script.py ls -la /tmp `'>' /tmp/test`. – P.P Oct 17 '20 at 19:22

3 Answers3

2

Single quotes already work exactly as you would wish. Probably you are doing something wrong with the string inside of your Python script.

In some more detail, the arguments when Bash is done parsing this command are (one per line)

python
script.py
-o
ls -la /tmp > /tmp/test

(The quotes were useful while Bash was parsing this command line, but they are gone now.)

You should easily be able to verify writhin Python that sys.argv[0] is script.py, sys.argv[1] is -o, and sys.argv[2] is the single-quoted string, sans quotes; all of these are strings (the shell really doesn't have any other primitive data type).

Backslash escaping all shell metacharacters individually would work as well here;

python script.py -o ls\ -la\ /tmp\ \>\ test

or double quoting the string; albeit in the shell, double quotes have slightly different semantics (variables will be interpolated and backticks evaluated, and a backslash can be used to escape backslashes, double quotes, dollar signs, and backticks, unlike in single quotes, where every character is preserved verbatim, and there is no way to escape a character.)

You don't reveal how exactly your code doesn't work, but I'd speculate that your problem is actually the opposite; you end up running something like ls '>' and get an error message that this file does not exist.

For the record, > is a redirection operator, not a command. The shell parses this into

ls
-la
/tmp

with standard oqtput redirected to the file /tmp/test. In terms of Python code,

with open('/tmp/test', 'w') as redirect:
    subprocess.run(['ls', '-la', '/tmp'], stdout=redirect)

Of course, if you want to support arbitrary shell features, you need a shell. The simplest fix here is probably

subprocess.run(sys.argv[2], shell=True)

See Actual meaning of shell=True in subprocess but here, I don't see any easy way to avoid the shell, short of by writing your own reimplementation.

tripleee
  • 175,061
  • 34
  • 275
  • 318
2

In general, when you want to use special characters literally, i.e., without their special meaning, you need to surround a string of characters with single quotation marks(or quotes) to strip all characters within the quotes of any special meaning they might have. It seems that you’re already applied quoting whilst passing your command line argument to the python script. So it should work as expected. For example let’s assume that your python script looks like this:

import argparse
parser = argparse.ArgumentParser(description='Your App')
parser.add_argument('-o', action="store", dest="command")
options = parser.parse_args()
print(options.command)

Invoking this script with python ./script.py -o 'ls -la /tmp > /tmp/test' will produce the below results as expected.

ls -la /tmp > /tmp/test

But you've already mentioned that it is not the behavior you're seeing. So the next thing you might check is the code in your actual python script to determine what’s going on there with the input value. It is most likely that the problem is in your python script. So, the next step I would do is inspecting your python script to understand that magic.

1218985
  • 7,531
  • 2
  • 25
  • 31
0

Try by escaping the character using a backslash \ before the greather than > symbol.