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
How to Monitor Newly Created File in a Directory with Bash
Preserve Environments Vars After Shell Script Finishes
How to Copy a File with '$' in Name in Linux
What Is Echo $? in Linux Terminal
Is It Good Practice to Use Mkdir as File-Based Locking on Linux
Linux: Handling a Segmentation Fault and Getting a Core Dump
Setting Up Jenkins Slave on MAC Os
Windows Equivalent of ./ (Current Directory)
How to Run Command During Docker Build Which Requires a Tty
Linux Assembler Error "Impossible Constraint in 'Asm'"
Objdump and Resolving Linkage of Local Function Calls
Best Way to Make Linux Web Services
Bash Scripting - Iterating Through "Variable" Variable Names for a List of Associative Arrays
Is There an Scp Variant of Mv Command