The Stack Overflow podcast is back! Listen to an interview with our new CEO.
188

In order from worst to best: DIRNAME="$(dirname $FILE)" will not do what you want if $FILE contains whitespace or globbing characters \[?*. DIRNAME=`dirname "$FILE"` is technically correct, but backticks are not recommended for command expansion because of the extra complexity when nesting them. DIRNAME=$(dirname "$FILE") is correct, but only because this ...


180

Short answer: Escape the % as \%: 0 * * * * echo hello >> ~/cron-logs/hourly/test`date "+\%d"`.log Long answer: The error message suggests that the shell which executes your command doesn't see the second back tick character: /bin/sh: -c: line 0: unexpected EOF while looking for matching '`' This is also confirmed by the second error message your ...


144

You are confusing two very different types of inputs. Standard input (stdin) Command line arguments These are different, and are useful for different purposes. Some commands can take input in both ways, but they typically use them differently. Take for example the wc command: Passing input by stdin: ls | wc -l This will count the lines in the output of ...


57

local t1=$(exit 1) tells the shell to: run exit 1 in a subshell; store its output (as in, the text it outputs to standard output) in a variable t1, local to the function. It's thus normal that t1 ends up being empty. ($() is known as command substitution.) The exit code is always assigned to $?, so you can do function0() { (exit 1) echo "$?" } to ...


52

Text between backticks is executed and replaced by the output of the command (minus the trailing newline characters, and beware that shell behaviors vary when there are NUL characters in the output). That is called command substitution because it is substituted with the output of the command. So if you want to print 5, you can't use backticks, you can use ...


45

You need to use "$(somecmd "$file")". Without the quotes, a path with a space will be split in the argument to somecmd, and it will target the wrong file. So you need quotes on the inside. Any spaces in the output of somecmd will also cause splitting, so you need quotes on the outside of the whole command substitution. Quotes inside the command ...


38

Newlines get swapped out at some points because they are special characters. In order to keep them, you need to make sure they're always interpreted, by using quotes: $ a="$(cat links.txt)" $ echo "$a" link1 link2 link3 Now, since I used quotes whenever I was manipulating the data, the newline characters (\n) always got interpreted by the shell, and ...


38

There is a practical difference. curl -sSL https://get.docker.com/ | sh starts curl and sh at the same time, connecting the output of curl with the input of sh. curl will carry out with the download (roughly) as fast as sh can run the script. The server can detect the irregularities in the timing and inject malicious code not visible when simply downloading ...


25

Portably: set -f # turn off globbing IFS=' ' # split at newlines only cmd $(cat <file) unset IFS set +f Or using a subshell to make the IFS and option changes local: ( set -f; IFS=' '; exec cmd $(cat <file) ) The shell performs field splitting and filename generation on the result of a variable or command substitution ...


25

It's not the printing, it's the command substitution that does that. It's defined to do that. From the POSIX description: The shell shall expand the command substitution by executing command in a subshell environment and replacing the command substitution with the standard output of the command, removing sequences of one or more {newline} characters at ...


24

There are several things to consider here. i=`cat input` can be expensive and there's a lot of variations between shells. That's a feature called command substitution. The idea is to store the whole output of the command minus the trailing newline characters into the i variable in memory. To do that, shells fork the command in a subshell and read its ...


23

Using arithmetic expansion: for (( k = 0; k < 50; ++k )); do a=$(( 2*k + 1 )) echo "$a" done Using expr: for (( k = 0; k < 50; ++k )); do a=$( expr 2 '*' "$k" + 1 ) echo "$a" done Using bc -l (-l not actually needed in this case as no math functions are used): for (( k = 0; k < 50; ++k )); do a=$( bc -l <<<"2*$k + 1" ) echo ...


22

The newlines were lost, because the shell had performed field splitting after command substitution. In POSIX Command Substitution section: The shell shall expand the command substitution by executing command in a subshell environment (see Shell Execution Environment) and replacing the command substitution (the text of command plus the enclosing "$()...


22

The function returns, but the command substitution blocks, because you created a background job, but you still have your stdout fd opened. Just close it by adding >/dev/null before the &. #!/bin/bash function start { leafpad >/dev/null & echo $! } PID=$(start) echo "PID is $PID" If you want your process to have also stdin, stdout, stderr ...


21

Use process substitution: diff <(cat /etc/passwd) <(cut -f2 /etc/passwd) <(...) is called process substitution. It converts the output of a command into a file-like object that diff can read from. While process substitution is not POSIX, it is supported by bash, ksh, and zsh.


21

You seem to be grepping the list of filenames, not the files themselves. <(cat files.txt) just lists the files. Try <(cat $(cat files.txt)) to actually concatenate them and search them as a single stream, or grep -i 'foo' $(cat files.txt) to give grep all the files. However, if there are too many files on the list, you may have problems with number ...


21

Once one is inside $(...), quoting starts all over from scratch. In other words, "..." and $(...) can nest within each other. Process substitution, $(...), can contain one or more complete double-quoted strings. Also, double-quoted strings may contain one or more complete process substitutions. But, they do not interlace. Thus, a double-quoted string ...


19

You can always show the effects of variable quoting with printf. Word splitting done on var1: $ var1="hello world" $ printf '[%s]\n' $var1 [hello] [world] var1 quoted, so no word splitting: $ printf '[%s]\n' "$var1" [hello world] Word splitting on var1 inside $(), equivalent to echo "hello" "world": $ var2=$(echo $var1) $ printf '[%s]\n' "$var2"...


19

Since back-ticks are often used, it makes sense to teach this syntactic construct. Of course, $() style command substitution should be emphasized as the default style (and standard conforming construct). Why are back-ticks still popular? Because they save one character in typing, and they are arguably less heavy on the eye.


18

You don't need to escape the quotes inside a subshell, since the current shell doesn't interpret them (it doesn't interpret anything from $( to ), actually), and the subshell doesn't know about any quotes that are above. Quoting a subshell at variable assignment is unnecessary too, for more info see man bash.


18

Yes, it is possible without even getting too far out of your way: $ $(exit 3); echo $? 3 $ foo="$(echo bar; exit 3)"; echo $?; echo $foo 3 bar


18

exit exits the current shell process¹. In $(resolve_ip), resolve_ip is running in a subshell process. You can do: my_ip=$(resolve_ip) || exit master_ip=$(resolve_ip "$hostname") || exit if [ "$my_ip" = "$master_ip" ]; ... For the main shell to exit (with the same exit code as the subshell) when the subshell exits with a non-zero exit status. Also, as ...


17

The $(command) syntax executes command in a subshell environment and replaces itself with the standard output of command. And, as Bash Manual says, $(< file) is just a faster equivalent of $(cat file) (that's not a POSIX feature, though). So when you run $(<array), Bash performs that substitution, then it uses the first field as the command's name and ...


16

Capturing exit status of commands The assignment of command output to the rep variable does not lose the exit status of the curl command; it is still available as $?. For more details, see How can I store the return value and/or output of a command in a variable?. Curl exit code for failed HTTP requests Usually if a requested HTTP resource isn’t available,...


14

diff <(cut -d: -f1 passwd2 | sort) <(sort aix_old) gives: 4,5c4 < harry < henry --- > ftp 7,8c6,7 < jennifer < julie --- > joe > juliet diff -y <(cut -d: -f1 passwd2 | sort) <(sort aix_old) gives: amadeus amadeus bill bill charlie ...


13

`` and $() is used for command execution, not for substituting it for variable content. So bash tries to execute varaible meaning in `` and returns the error that it is a directory. Just write cat ${path}test and it will work in the way you want. For more information read about bash variables and command substitution.


13

I tend to use this: command1 | xargs -I{} command2 {} Pass output of command1 through xargs using substitution (the braces) to command2. If command1 is find be sure to use -print0 and add -0 to xargs for null terminated strings and xargs will call command2 for each thing found. In your case (and taking the sed line from @Janos): command1 -p=aaa -v=bbb -i=...


13

Exit code was stored in $? variable. Using Command Substitution only capture the output, you should use (...) to create subshell: #!/bin/bash func() { (exit 1) local t1=$? printf '%d\n' "$t1" } func


13

Okay, let's break this down. A subshell executes its contents in a chain (i.e., it groups them). This actually makes intuitive sense as a subshell is created simply by surrounding the chain of commands with (). But, aside from the contents of the subshell being grouped together in execution, you can still use a subshell as if it were a single command. That ...


13

Ksh93 does a lot to avoid forks. I have no idea how it knows how to handle the first case, as a truss shows that it only calls one write(2) call with the final result. It may be that David scans the command in macro.c and knows that he may handle "echo" internally. What I can say is that I rewrote the parser and the interpreter of the "Bourne Shell" last ...


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