A way to prevent bash from parsing command line w/out using escape symbols

2.8k Views Asked by At

I'm looking for a way (other than ".", '.', \.) to use bash (or any other linux shell) while preventing it from parsing parts of command line. The problem seems to be unsolvable How to interpret special characters in command line argument in C?

In theory, a simple switch would suffice (e.g. -x ... telling that the string ... won't be interpreted) but it apparently doesn't exist. I wonder whether there is a workaround, hack or idea for solving this problem. The original problem is a script|alias for a program taking youtube URLs (which may contain special characters (&, etc.)) as arguments. This problem is even more difficult: expanding "$1" while preventing shell from interpreting the expanded string -- essentially, expanding "$1" without interpreting its result

3

There are 3 best solutions below

17
On

Use a here-document:

myprogramm <<'EOF'
https://www.youtube.com/watch?v=oT3mCybbhf0
EOF

If you wrap the starting EOF in single quotes, bash won't interpret any special chars in the here-doc.

5
On

Short answer: you can't do it, because the shell parses the command line (and interprets things like "&") before it even gets to the point of deciding your script/alias/whatever is what will be run, let alone the point where your script has any control at all. By the time your script has any influence in the process, it's far too late.

Within a script, though, it's easy to avoid most problems: wrap all variable references in double-quotes. For example, rather than curl -o $outputfile $url you should use curl -o "$outputfile" "$url". This will prevent the shell from applying any parsing to the contents of the variable(s) before they're passed to the command (/other script/whatever).

But when you run the script, you'll always have to quote or escape anything passed on the command line.

0
On

Your spec still isn't very clear. As far as I know the problem is you want to completely reinvent how the shell handles arguments. So… you'll have to write your own shell. The basics aren't even that difficult. Here's pseudo-code:

while true:
    print prompt
    read input
    command = (first input)
    args = (argparse (rest input))
    child_pid = fork()
    if child_pid == 0: // We are inside child process
        exec(command, args) // See variety of `exec` family functions in posix
    else: // We are inside parent process and child_pid is actual child pid
        wait(child_pid) // See variety of `wait` family functions in posix

Your question basically boils down to how that "argparse" function is implemented. If it's just an identity function, then you get no expansion at all. Is that what you want?