Hacker News new | ask | show | jobs
by bmacho 640 days ago
> Wait! The fact that arguments with a leading hyphen are interpreted as options is not bash's fault. It's ingrained in the convention of UNIX tools and there's nothing bash can do to mitigate it. You would have the same problem if you got rid of any shell and directly invoked commands from Python or C.

A better system shell could make it easy to define shims for the existing programs. Also it could make their calling easier, e.g. with named arguments. So when you wanted to delete your file called -rf, you would say

  rm(file="-rf")
or something like that, with your preferred syntax. It would be much safer than just pass big strings as arguments, where spaces separate the different arguments, also spaces can appear in the arguments, also arguments can be empty. Bash or Posix sh is not very good at safely invoking other programs, or at handling files.
1 comments

What you're suggesting is that the shell should have every possible command builtin and not call external programs.

Let's analyze your example with 'rm': it works as long as 'rm' is an internal routine. If it's an external program, independently of the syntax you use to specify the arguments, sooner or later the shell will need to actually call the 'rm' executable, and to pass '-rf' to it as argument number 1. The 'rm' executable will then examine its arguments, see that the first one begins with a hyphen and interpret it as an option.

As I said, the only way to avoid all this would be to replace 'rm' with an internal routine. Then you would replace 'cp' and 'ln', and what else? Of course 'echo' and 'printf', 'cat', 'ls', 'cd' maybe, why not 'find' and 'grep'? What about 'head', 'tail', 'cut'? Don't forget 'sed' and 'awk'... the list is getting longer and longer. Where do you draw the line?

Seriously, the only mitigation would be to define a function to 'sanitize' an argument to make it appear as a file if used as an argument to an external program. Something like:

  force_file() {
    case "$1" in
      -*) echo "./$1" ;;
      *)  echo "$1" ;;
    esac
}

This doesn't work with 'echo' though.