944

This technique allows for a variable to be assigned a value if another variable is either empty or is undefined. NOTE: This "other variable" can be the same or another variable. excerpt ${parameter:-word} If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted. NOTE: This form also ...


699

sed is the stream editor, in that you can use | (pipe) to send standard streams (STDIN and STDOUT specifically) through sed and alter them programmatically on the fly, making it a handy tool in the Unix philosophy tradition; but can edit files directly, too, using the -i parameter mentioned below. Consider the following: sed -i -e 's/few/asd/g' hello.txt s/...


506

I'd recommend getting it directly from a DNS server. Most of the other answers below all involve going over HTTP to a remote server. Some of them required parsing of the output, or relied on the User-Agent header to make the server respond in plain text. Those change quite frequently (go down, change their name, put up ads, might change output format etc.). ...


424

Always use double quotes around variable substitutions and command substitutions: "$foo", "$(foo)" If you use $foo unquoted, your script will choke on input or parameters (or command output, with $(foo)) containing whitespace or \[*?. There, you can stop reading. Well, ok, here are a few more: read — To read input line by line with the read builtin, use ...


340

First, note that the -z test is explicitly for: the length of string is zero That is, a string containing only spaces should not be true under -z, because it has a non-zero length. What you want is to remove the spaces from the variable using the pattern replacement parameter expansion: [[ -z "${param// }" ]] This expands the param variable and ...


333

Actually, the second form touch filename doesn't delete anything from the file - it only creates an empty file if one did not exist, or updates the last-modified date of an existing file. And the third filename < /dev/null tries to run filename with /dev/null as input. cp /dev/null filename works. As for efficient, the most efficient would be truncate -s ...


318

No, this will not prevent the script from crashing. If any errors occur in the tar process (e.g.: permission denied, no such file or directory, ...) the script will still crash. This is because of using > /dev/null 2>&1 will redirect all your command output (both stdout and stderr) to /dev/null, meaning no outputs are printed to the terminal. By ...


312

awk '{$1=$1;print}' or shorter: awk '{$1=$1};1' Would trim leading and trailing space or tab characters1 and also squeeze sequences of tabs and spaces into a single space. That works because when you assign something to one of the fields, awk rebuilds the whole record (as printed by print) by joining all fields ($1, ..., $NF) with OFS (space by default). ...


281

systemctl has an is-active subcommand for this: systemctl is-active --quiet service will exit with status zero if service is active, non-zero otherwise, making it ideal for scripts: systemctl is-active --quiet service && echo Service is running If you omit --quiet it will also output the current status to its standard output. As pointed out by ...


279

tmpfile=$(mktemp /tmp/abc-script.XXXXXX) : ... rm "$tmpfile" You can make sure that a file is deleted when the scripts exits (including kills and crashes) by opening a file descriptor to the file and deleting it. The file keeps available (for the script; not really for other processes but /proc/$PID/fd/$FD is a work-around) as long as the file descriptor is ...


256

IFS stands for "internal field separator". It is used by the shell to determine how to do word splitting, i. e. how to recognize word boundaries. Try this in a shell like bash (other shells may handle this differently, for example zsh): mystring="foo:bar baz rab" for word in $mystring; do echo "Word: $word" done The default value for IFS consists of ...


252

Sample task task(){ sleep 0.5; echo "$1"; } Sequential runs for thing in a b c d e f g; do task "$thing" done Parallel runs for thing in a b c d e f g; do task "$thing" & done Parallel runs in N-process batches N=4 ( for thing in a b c d e f g; do ((i=i%N)); ((i++==0)) && wait task "$thing" & done ) It's also ...


248

With bash 4.2 and above, you can do: ${var::-1} Example: $ a=123 $ echo "${a::-1}" 12 Notice that for older bash ( for example, bash 3.2.5 on OS X), you should leave spaces between and after colons: ${var: : -1}


243

Preamble First, I'd say it's not the right way to address the problem. It's a bit like saying "you should not murder people because otherwise you'll go to jail". Similarly, you don't quote your variable because otherwise you're introducing security vulnerabilities. You quote your variables because it is wrong not to (but if the fear of the jail can ...


239

One problem with your first command is that you redirect stderr to where stdout is (if you changed the $ to a & as suggested in the comment) and then, you redirected stdout to some log file, but that does not pull along the redirected stderr. You must do it in the other order, first send stdout to where you want it to go, and then send stderr to the ...


227

I guess you're looking for: if [ "$PHONE_TYPE" != "NORTEL" ] && [ "$PHONE_TYPE" != "NEC" ] && [ "$PHONE_TYPE" != "CISCO" ] The rules for these equivalents are called De Morgan's laws and in your case meant: not(A || B || C) => not(A) && not(B) && not (C) Note the change in the boolean operator or and and. Whereas ...


219

Parsing the output of git status is a bad idea because the output is intended to be human readable, not machine-readable. There's no guarantee that the output will remain the same in future versions of Git or in differently configured environments. UVVs comment is on the right track, but unfortunately the return code of git status doesn't change when there ...


213

If you don't mind being limited to single-letter argument names i.e. my_script -p '/some/path' -a5, then in bash you could use the built-in getopts, e.g. #!/bin/bash while getopts ":a:p:" opt; do case $opt in a) arg_1="$OPTARG" ;; p) p_out="$OPTARG" ;; \?) echo "Invalid option -$OPTARG" >&2 ;; esac done printf "Argument ...


195

You were pretty close with your example. It works just fine when you use it with arguments such as these. Sample script: $ more ex.bash #!/bin/bash echo $1 $2 Example that works: $ ssh serverA "bash -s" < ./ex.bash "hi" "bye" hi bye But it fails for these types of arguments: $ ssh serverA "bash -s" < ./ex.bash "--time" "bye" bash: --: invalid ...


194

There's already a UNIX command for this: du Just do: du -ach As per convention you can add one or more file or directory paths at the end of the command. -h is an extension to convert the size into a human-friendly format, -a gives you the "apparent" size (file size instead of disk usage), and -c gives a total at the end.


191

Here's how I change all the file extensions in the current directory on Debian. rename "s/oldExtension$/newExtension/" *.txt (This is the Perl rename command, not the util-linux one. See Why is the rename utility on Debian/Ubuntu different than the one on other distributions, like CentOS?)


191

shift is a bash built-in which kind of removes arguments from the beginning of the argument list. Given that the 3 arguments provided to the script are available in $1, $2, $3, then a call to shift will make $2 the new $1. A shift 2 will shift by two making new $1 the old $3. For more information, see here: http://ss64.com/bash/shift.html http://www.tldp....


178

for i in 1 2 3 4 5; do command && break || sleep 15; done Replace "command" with your command. This is assuming that "status code=FAIL" means any non-zero return code. Variations: Using the {..} syntax. Works in most shells, but not BusyBox sh: for i in {1..5}; do command && break || sleep 15; done Using seq and passing along the exit ...


177

An alternative very lightweight option is just to 'tail' everything but the first line (this can be an easy way to remove file headers generally): # -n +2 : start at line 2 of the file. tail -n +2 file.txt > file.stdout Following @Evan Teitelman, you can: tail -n +2 file.txt | sponge file.txt To avoid a temporary file. Another option might be: echo "...


172

NOTE: This is about external IP address (the one that the servers on the Internet see when you connect to them) - if you want internal IP address (the one that your own computer is using for connections, which may be different) see this answer. TL;DR - Fastest methods in 2015 The fastest method using DNS: dig +short myip.opendns.com @resolver4.opendns.com ...


166

A subshell starts out as an almost identical copy of the original shell process. Under the hood, the shell calls the fork system call1, which creates a new process whose code and memory are copies2. When the subshell is created, there are very few differences between it and its parent. In particular, they have the same variables. Even the $$ special variable ...


165

First, separate zsh from the rest. It's not a matter of old vs modern shells: zsh behaves differently. The zsh designers decided to make it incompatible with traditional shells (Bourne, ksh, bash), but easier to use. Second, it is far easier to use double quotes all the time than to remember when they are needed. They are needed most of the time, so you'll ...


165

The reason for this pattern is that maintainer scripts in Debian packages tend to start with set -e, which causes the shell to exit as soon as any command (strictly speaking, pipeline, list or compound command) exits with a non-zero status. This ensures that errors don't accumulate: as soon as something goes wrong, the script aborts. In cases where a ...


150

The right answer is still missing: todate=$(date -d 2013-07-18 +%s) cond=$(date -d 2014-08-19 +%s) if [ $todate -ge $cond ]; then break fi Note that this requires GNU date. The equivalent date syntax for BSD date (like found in OSX by default) is date -j -f "%F" 2014-08-19 +"%s"


146

You can change the here-doc operator to <<-. You can then indent both the here-doc and the delimiter with tabs: #! /bin/bash cat <<-EOF indented EOF echo Done Note that you must use tabs, not spaces to indent the here-doc. This means the above example won't work copied (Stack Exchange replaces tabs with spaces). There can not be any ...


Only top voted, non community-wiki answers of a minimum length are eligible