I want to get the full command line as it was typed.
This:
" ".join(sys.argv[:])
doesn't work here (deletes double quotes). Also I prefer not to rejoin something that was parsed and split.
Any ideas?
I want to get the full command line as it was typed.
This:
" ".join(sys.argv[:])
doesn't work here (deletes double quotes). Also I prefer not to rejoin something that was parsed and split.
Any ideas?
In a Unix environment, this is not generally possible...the best you can hope for is the command line as passed to your process.
Because the shell (essentially any shell) may munge the typed command line in several ways before handing it to the OS for execution.
If you're on Linux, I'd suggest monkeying with the
~/.bash_history
file or the shellhistory
command, although I believe the command must finish executing before it's added to the shell history.I started playing with:
But I'm getting weird behavior where the shell doesn't seem to be completely flushing to the
.bash_history
file.Here's how you can do it from within the Python program to get back the full command string. Since the command-line arguments are already handled once before it's sent into
sys.argv
, this is how you can reconstruct that string.Example:
Invoking like this from the terminal,
will give the same string in commandstring:
You're too late. By the time that the typed command gets to Python your shell has already worked its magic. For example, quotes get consumed (as you've noticed), variables get interpolated, etc.
On Linux there is
/proc/<pid>/cmdline
that is in the format ofargv[]
(i.e. there is 0x00 between all the lines and you can't really know how many strings there are since you don't get the argc; though you will know it when the file runs out of data ;).You can be sure that that commandline is already munged too since all escaping/variable filling is done and parameters are nicely packaged (no extra spaces between parameters, etc.).
*nix
Look at the initial stack layout (Linux on i386) that provides access to command line and environment of a program: the process sees only separate arguments.
You can't get the command-line as it was typed in the general case. On Unix, the shell parses the command-line into separate arguments and eventually
execv(path, argv)
function that invokes the corresponding syscall is called.sys.argv
is derived fromargv
parameter passed to theexecve()
function. You could get something equivalent using" ".join(map(pipes.quote, argv))
though you shouldn't need to e.g., if you want to restart the script with slightly different command-line parameters thensys.argv
is enough (in many cases), see Is it possible to set the python -O (optimize) flag within a script?There are some creative (non-practical) solutions:
Windows
On Windows the native
CreateProcess()
interface is a string but python.exe still receives arguments as a list.subprocess.list2cmdline(sys.argv)
might help to reverse the process.list2cmdline
is designed for applications using the same rules as the MS C runtime—python.exe
is one of them.list2cmdline
doesn't return the command-line as it was typed but it returns a functional equivalent in this case.On Python 2, you might need
GetCommandLineW()
, to get Unicode characters from the command line that can't be represented in Windows ANSI codepage (such as cp1252).