What Is the Meaning of !#:* !#:1- in a Bash Command

What is the meaning of !#:* !#:1- in a bash command?

It's using bash's history substitution mechanism.

Specifically, !# refers to the current line (up to but not including the location of the !# itself). !#:* is the part of that line after the command name (so, in this case, "This is a sentence."). !#:1- is the same as !#:* except that it omits the last word (so it doesn't include the second copy of "This is a sentence" that we just added via the !#:*).

The end result is a line with three copies of This is a sentence. echoed into a file named text3.

Echoing the last command run in Bash?

The command history is an interactive feature. Only complete commands are entered in the history. For example, the case construct is entered as a whole, when the shell has finished parsing it. Neither looking up the history with the history built-in (nor printing it through shell expansion (!:p)) does what you seem to want, which is to print invocations of simple commands.

The DEBUG trap lets you execute a command right before any simple command execution. A string version of the command to execute (with words separated by spaces) is available in the BASH_COMMAND variable.

trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG

echo "last command is $previous_command"

Note that previous_command will change every time you run a command, so save it to a variable in order to use it. If you want to know the previous command's return status as well, save both in a single command.

cmd=$previous_command ret=$?
if [ $ret -ne 0 ]; then echo "$cmd failed with error code $ret"; fi

Furthermore, if you only want to abort on a failed commands, use set -e to make your script exit on the first failed command. You can display the last command from the EXIT trap.

set -e
trap 'echo "exit $? due to $previous_command"' EXIT

Note that if you're trying to trace your script to see what it's doing, forget all this and use set -x.

What does 2 &1 mean?

File descriptor 1 is the standard output (stdout).

File descriptor 2 is the standard error (stderr).

At first, 2>1 may look like a good way to redirect stderr to stdout. However, it will actually be interpreted as "redirect stderr to a file named 1".

& indicates that what follows and precedes is a file descriptor, and not a filename. Thus, we use 2>&1. Consider >& to be a redirect merger operator.

Meaning of $? (dollar question mark) in shell scripts

This is the exit status of the last executed command.

For example the command true always returns a status of 0 and false always returns a status of 1:

true
echo $? # echoes 0
false
echo $? # echoes 1

From the manual: (acessible by calling man bash in your shell)

?       Expands to the exit status of the most recently executed foreground pipeline.

By convention an exit status of 0 means success, and non-zero return status means failure. Learn more about exit statuses on wikipedia.

There are other special variables like this, as you can see on this online manual: https://www.gnu.org/s/bash/manual/bash.html#Special-Parameters

Make a Bash alias that takes a parameter?

Bash alias does not directly accept parameters. You will have to create a function.

alias does not accept parameters but a function can be called just like an alias. For example:

myfunction() {
#do things with parameters like $1 such as
mv "$1" "$1.bak"
cp "$2" "$1"
}

myfunction old.conf new.conf #calls `myfunction`

By the way, Bash functions defined in your .bashrc and other files are available as commands within your shell. So for instance you can call the earlier function like this

$ myfunction original.conf my.conf

\r': command not found - .bashrc / .bash_profile

When all else fails in Cygwin...

Try running the dos2unix command on the file in question.

It might help when you see error messages like this:

-bash: '\r': command not found

Windows style newline characters can cause issues in Cygwin.

The dos2unix command modifies newline characters so they are Unix / Cygwin compatible.

CAUTION: the dos2unix command modifies files in place, so take precaution if necessary.

If you need to keep the original file, you should back it up first.

Note for Mac users: The dos2unix command does not exist on Mac OS X.

Check out this answer for a variety of solutions using different tools.


There is also a unix2dos command that does the reverse:

It modifies Unix newline characters so they're compatible with Windows tools.

If you open a file with Notepad and all the lines run together, try unix2dos filename.

understanding bash exec 1 &2 command

exec is a built-in Bash function, so it can have special behavior that an external program couldn't have. In particular, it has the special behavior that:

If COMMAND is not specified, any redirections take effect in the current shell.

(That's quoting from the message given by help exec.)

This applies to any sort of redirection; you can also write, for example, any of these:

exec >tmp.txt
exec >>stdout.log 2>>stderr.log
exec 2>&1

(It does not, however, apply to pipes.)

What is the meaning of ${0%/*} in a bash script?

It is called Parameter Expansion. Take a look at this page and the rest of the site.

What ${0%/*} does is, it expands the value contained within the argument 0 (which is the path that called the script) after removing the string /* suffix from the end of it.

So, $0 is the same as ${0} which is like any other argument, eg. $1 which you can write as ${1}. As I said $0 is special, as it's not a real argument, it's always there and represents name of script. Parameter Expansion works within the { } -- curly braces, and % is one type of Parameter Expansion.

%/* matches the last occurrence of / and removes anything (* means anything) after that character. Take a look at this simple example:

$ var="foo/bar/baz"
$ echo "$var"
foo/bar/baz
$ echo "${var}"
foo/bar/baz
$ echo "${var%/*}"
foo/bar


Related Topics



Leave a reply



Submit