When using Git, when would I use one hyphen (-) over two hyphens (--)? - linux

In Git, when I am performing a commit with add, I can use
git commit -am "My commit"
When I see examples of git log or in most other cases we use
git log --online
But I do not understand when I'd use one hyphen (-) or two hyphens (--). Can anyone please explain?

There is no big difference between - and --. It is just a convention in unix to use:
- when the option is one letter. In this case you can combine then: -am is equivalent to -a -m
-- when the option is a word.
-- without a word is used to separate options from arguments, that way you can use arguments starting with hyphen without having them interpreted as an option
Some options have the two forms (one letter or one word), some have only one of the two forms. Check the help of each command to find it.
git commit -am "My commit"
# is equivalent to
git commit --all --message "My commit"
Also you can read this question on Super User to learn more about this, as suggested by melpomene.

I've "OBSERVED" that single hyphen is used for single character options and double hyphens are used for multiple character option in git (and several other tools).
This is an indication to the program that whatever it sees after -- should be treated a single option. For example, --online specifies that "online" is an option. But if we use -online, we specify o,n,I,i,n,e are options.
However, this also depends on the tools we use. Most tools follow this pattern, which I think makes the parsing easier. But I've seen few program that can can take in multiple character option with a single hyphen. For example, "java -version" works just fine.

It largely depends on the command you're executing. Let's take git-add as an example.
The possible parameters to it are as follows:
git add [--verbose | -v] [--dry-run | -n] [--force | -f] [--interactive | -i] [--patch | -p]
[--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]]
[--intent-to-add | -N] [--refresh] [--ignore-errors] [--ignore-missing]
[--chmod=(+|-)x] [--] [<pathspec>…​]
I picked this one in particular because there's a nice mix of short and long-form flags, as well as the double-hyphen in a peculiar place, which I'll get to in a moment.
First and foremost, the key difference between a single hyphen and a double-hyphened flag largely depend on what the command supports. You'll notice in git-add, there are some flags which use double-hyphens as a longer-form command, and the single-hyphen flags as a shorter way to express the same command. In that vein, --verbose and -v accomplish the same thing with different syntaxes.
That's established by convention, and is there for convenience's sake.
Now, to the point of the double-hyphen. In Unix-based systems, a double-hyphen following the flags represents the end of the command, which allows you to specify paths which would conflict with any of the flags present or above. As an example, if you have (for whatever reason) a file named -n, you can add it to Git by:
git add -- -n
So, to summarize:
Use a single hyphen for shorthand flags if it's supported.
Use a double-hyphen for long-hand flags if you remember the command name, or if there's no alternative (like in --ignore-missing).
Use a double-hyphen to signify the end of a command.

Using one hyphen - is to use shortcut parameters (one letter for each parameter) for parameters the most commonly used.
That's a Unix convention.
They are intended to be used only by the user in the command line because they are convenient.
Everywhere else (especially in scripts) , prefer the equivalent with 2 hyphens --, which is a good practice, to make it more meaningful for the future one (perhaps you) that will have to read it.
You could see parameters that have a one letter shortcut using the parameter --help on every Unix command.

Related

Usage of sed to add a prefix for a string in linux

In my problem statement I would like to replace a word with a prefix
sed 's/hello-world/'"$1"'-hello-world/g' test.sql
Here $1 is any prefix passed as parameter to the shell script
In this case in the first go it works absolutely fine.
Let's assume "prefix=new"
It replaces as new-hello-world which is a perfect output.
If i re-run the command again I get new-new-hello-world which is not intended
Run it again i would get new-new-new-hello-world which is not intended
How can we search and replace it as new-hello-world no matter how many times it is run? Using a regex is also fine.
To make it idempotent, just check first that it doesn't already match. eg:
sed "/$1-hello-world/!s/hello-world/$1-hello-world/g" test.sql
This is not particularly robust, and will fail if the original documents contains the line new-hello-world hello-world, but is probably sufficient for your needs. (You need to worry more about / characters in the prefix, so if you want a robust solution there's a fair bit of work to be done.)

Difference between the 3 option syntax for commands in bash

In Linux command line, one can use either of two ways to pass options to commands. Either we can use the short option format which uses a single dash followed by a single letter, for example: -o or the long option format which uses two consecutive dashes followed by a word, for example: --option. But recently I came across some commands which in my thinking uses a 'hybrid' of both the formats, which uses a single dash followed by a word, for example: -option. Now I'm not talking about a commands where you can stick multiple short options together like ls -lisa. I'm talking about options where the word after the single dash is just one option and not multiple short options strung together.
I don't seem to understand why there's a third option. Because what I know about the Linux command line is you can have only a short form format or a long form format. Where did the third format came from?
It's actually confusing because sometimes you cannot be sure if the third format is really a dash followed by one option or a dash followed by multiple short options.
This is not a bash issue. All programs have their on way of handling the options/flags. There are many different styles:
the singe letter style with a single hyphen, for example:
ls -l
the mnemonic-style with double dashes, which seems a preference for GNU-stuff, for example, ls --size
the variable=value-style, for example dd if=file of=otherfile
options without dashes, as in tar cvzf arghive.tgz
You could even use a + instead of a - (as in date +%m).
etcetera.
It is important to understand that bash just passes these options to the programs/commands. So, in the programs you will generally see:
int main(int argc, char *argv[]){
(c-code example). In that case, argv[0] will point to the program-name (to simplify things a bit) and argv[1] will point to the first argument. Depending on the program, that may be different.
A quick scan through the built-in commands reveals that the built-ins always seem to use the minus-single letter (-a) for specifying options.
I think you are confusing which component does which part of the parsing.
The command line you type into bash gets parsed twice. First it gets parsed by bash. At this stage, spaces are used to separate the different parameters. Quotes and escapes are being taken into consideration. Wildcards are expanded, and $ variables are substituted.
At the end of this phase, we are left with a command line that has a list of strings, the first of which describes the command to be executed. At this point, bash calls execve, and passes it that list of strings.
The next phase of parsing is optional, and is up to each program to carry out. Most programs call getopt_long, a library function that parses options. The one and two dash convention you mention is applied by it (as well as it's older sibling, getopt).
It is, however, up to each program to parse its own parameters. Many programs use getopt_long, which is why you feel, correctly, that it is a standard. Some, however, do not. Those who do not follow their own way.
That's just how things are.
For your programs, you should try to use either getopt_long or some compatible solution, as that causes the least amount of confusion for users.

cat `-q` file (in linux) - passing operands that look like options

I have a file whose name is -q (It looks like this is made by accident)
I want to see it’s content, so I tried these
$ cat '-q'
$ cat "-q"
$ cat $'-q'
But nothing worked.(All gives same error cat: invalid option -- 'q')
Is there any way to see it’s content?
sjsam's helpful answer offers viable solutions, but it's worth digging deeper:
Arguments passed to Unix utilities (such as cat) can be divided into two groups (using POSIX terminology):
options (e.g., -l; depending on the option's definition, possibly followed by an option-argument) - switches that modify the utility's basic behavior.
operands (e.g., a filename) - the data that the utility operates on.
POSIX requires all options, if any, to come before any operands, but GNU utilities relax this requirement to allow intermingling options and operands for convenience.
Either way, a - followed by a letter or digit generally implies an option.
So as to allow passing operands that happen to start with -, special option -- can be used to tell any utility: treat any subsequent arguments as operands, even if they look like options.
Since operand -q in this case looks like an option, preceding it with -- to mark it as an operand is a must.
As for how to pass string -q itself as an argument:
-q contains no shell metacharacters, so the shell passes it as-is to cat - no quoting needed.
Quoting ('-q', "-q", $'-q', \-q) does no harm in this case, but has absolutely no effect here, because the shell - after having applied any expansions - simply removes any quoting characters (a process called quote removal) before passing the word to cat (as Charles Duffy notes in comments on the question).
to create a file named -q do
touch -- "-q"
and to view its contents
cat -- '-q' # Used single quotes to treat anything inside as literal characters
should do it. -- means what follows should be treated as a positional parameter.
Pls take time to look at #rici's [ answer ] which reminds some substle aspects regarding single vs double quotes.

How to accept the 'Did you mean?' terminal/git suggestion

This is a simple question.
Sometimes on a Terminal when you make a small mistake the console asks ¿Did you mean ...? - ¿Is there a way to quicky accept the suggestion?.
For example:
$ git add . -all
error: did you mean `--all` (with two dashes ?)
Is there a command that repeats the last line, but with the two dashes?
If you forget to write sudo, you can just do sudo !! and it will solve your problem. I want to know if there is something similar but for the error: did you mean case.
In the case of...
$ git add . -all
error: did you mean `--all` (with two dashes ?)
...the message is written by git directly to the terminal. This means that bash has no way of knowing what message was written; it would be literally impossible to implement anything in the shell that could automate putting that correction in place without making programs run under the shell considerably less efficient (by routing their output through the shell rather than directly to the terminal) and changing their behavior (if they ever call isatty() on their stdout or stderr).
That said, you can certainly run
^-all^--all
...if you haven't turned history expansion off, as with set +H (if off, it can be reenabled with set -H). I typically do turn this functionality off, myself; it's often more trouble than it's worth (making commands which would work perfectly well in scripts break in interactive shells when they use characters that history expansion is sensitive to, particularly !).

Hyphen usage on Linux command options

Until recently, I was under the impression that by convention, all Linux command options were required to be prefixed by a hyphen (-). So for example, the instruction ls –l executes the ls command with the l option (here we can see that the l option is prefixed by a hyphen).
Life was good until I got to the chapter of my Linux for beginners book that explained the ps command. There I learned that I could write something like ps u U xyz where as far as I can tell, theu and U are options that are not required to be prefixed by a hyphen. Normally, I would have expected to have to write that same command as something like ps –uU xyz to force the usage of a hyphen.
I realize that this is probably a stupid question but I was wondering if there is a particular reason as to why the ps command does not follow what I thought was the standard way of specifying command options (prefixing them with hyphens). Why the variation? Is there a particular meaning to specifying hyphen-less options like that?
There are a handful of old programs on Unix that were written when the conventions were not as widely adopted, and ps is one of them. Another example is tar, although it has since been updated to allow options both with and without the - prefix.
IMO the best practice concerning hyphenation is to use them as the default go-to. More times than not, they have accepted hyphen prefixes to most or all flags/options available for commands. Happy to be corrected if I am wrong in this instance. I am still new to this myself! :)

Resources