Sharedswc-shell-novice / katja.mdOpen in CoCalc
Authors: Katja Berčič, Samuel Lelièvre
Views : 3

Jan's comments

On flags and arguments

Bash parses the command line input into words. It executes the first word and passes the rest of them to it as an array. Its up to the program to process this array. Most programs will accept an undefined number of arguments. It is pretty standard that the flags need to come before the arguments.

It is customary to group short options and to interpret every argument that starts with a dash as an option. Short flags start with a - and can be combined while long flags start with -- and cannot. In the case of a sequence of files that needs to be explicitly marked, it is also customary to insert -- before the list to signal that no options will follow.

Most programs with a simple command line syntax use the getopt(3) function in the C library on Unix. This function handles basic parsing and behaves as described above.

  • It depends on the program whether it accepts options together (ls -lahFG) or it requires them separately (ls -l -a -h -F -G).
  • Some programs consider everything that starts with a - as a flag and would happily accept exec dirpath -F.
  • Similarly, it depends on the program whether it requires the dash for flags or not (i.e. tar xjf, ps aux)
  • ls dir -F should work according to the logic above. It is up to ls that it does not.
  • Jan is pretty sure there exists a program that accepts a fixed number of arguments.
  • Openvms solves option parsing at the system level - the console is super uniform and all commands follow a standard.
  • Flags always commute except when noted otherwise in the manpage. Typical examples of noncommuting programs are ffmpeg and convert. An average option is just a boolean flag and an average program does not have semantically overlapping flags. When the flags do overlap, they take effect from first to last. With overlapping booleans, only the last one would take effect (but that's up to the program).
  • An option can have further arguments, in those cases, check the manpage for behaviour. Shell scripts usually use the --long=param syntax while compiled programs use --long param.
  • There are always exceptions: gcc -vomit-frame-pointer. Programs with excessively many options always never follow the long option convention.
  • Finally, there are programs with subcommands like git. The well behaved breeds (btrfs, svn, ip) will let you shorten the subcommands until they become ambiguous: btrfs bal star instead of btrfs balance start, btrfs fi sh /path instead of btrfs filesystem show /path or svn stat instead of svn status. Git does not accept shorthands, partly due to the underlying architecture.
  • gcc has its own option system. -f<opt> options control optimisation types and code transformations, -W<opt> control which warnings show, etc. One of the options is -fomit-frame-pointer (do not save the frame pointer in function call, which makes life harder for the debugger but speeds up function calls).

Excercise

With a basic understanding of Bash and programming, you should be able to explain why there can not be less whitespace in the following (except for the cosmetic ones after ;):

if [ "$USER" == "$(id -nu)" ]; then echo tautology; fi

A frustrating Windows example

The following code works in the DOS shell, but not on Unix.

cd..

On Windows, they probably made a special case or they do not treat a dot as a part of a word. A Unix shell tokenises according to whitespace. In this case, it would try to run a program called cd.., which does not exist.

What's really going to bake your noodle later on: you can not write a program like that, because the current working directory is a runtime attribute of a process. Such a program could only change its own current working directory and not also its parent shell's. After the program terminated, the shell would return you to the directory in which you started the program. All paths (except those starting with /) are resolved with respect to the current working directory.