Why is this working:
mkdir /dir/test{1,2,3}
and this not?
{chown httpd,chmod 700} /dir/test1
-bash: {chown: command not found
My Bash Version is: GNU bash, version 4.2.46(2)-release
Why is this working:
mkdir /dir/test{1,2,3}
and this not?
{chown httpd,chmod 700} /dir/test1
-bash: {chown: command not found
My Bash Version is: GNU bash, version 4.2.46(2)-release
Your brace expansion is not valid. A brace expansion must be one word in the shell.
A word is a string delimited by unquoted spaces (or tabs or newlines, by default), and the string {chown httpd,chmod 700}
consists of the three separate words {chmod
, http,chmod
and 700}
and would not be recognised as a brace expansion.
Instead, the shell would interpret the line as a {chown
command, executed with the arguments http,chmod
, 700}
and /dir/test1
.
The simplest way to test this is with echo
:
$ echo {chown httpd,chmod 700} /dir/test1
{chown httpd,chmod 700} /dir/test1
$ echo {"chown httpd","chmod 700"} /dir/test1
chown httpd chmod 700 /dir/test1
Note that even if your brace expansion had worked, the command would have been nonsensical.
Just write two commands,
chown http /dir/test1
chmod 700 /dir/test1
mkdir test{,2," three",\ four}
(creates directories "test", "test2", "test three", "test four")
– Freddy
Feb 11 '19 at 13:40
eval {'chown http','chmod 0666'}' /tmp/foo;'
.
–
Feb 11 '19 at 15:13
eval
and with very careful quoting, it would be possible to do what the user wanted.
– Kusalananda
Feb 11 '19 at 15:22
PATH
.
– JoL
Feb 11 '19 at 16:29
eval {'"chown http"', ...}
– Kusalananda
Feb 11 '19 at 16:31
{"chown httpd","chmod 700"} /dir/test1
and got bash: chown httpd: command not found
.
– JoL
Feb 11 '19 at 16:33
eval
.
– JoL
Feb 11 '19 at 16:36
bash
's history expansion to use the last command line argument as in !#:1
. https://askubuntu.com/a/1109025/295286
– Sergiy Kolodyazhnyy
Feb 11 '19 at 22:12
bash
-like shell in which that simply doesn't work, whether sensical or nonsensical.
–
Feb 12 '19 at 08:16
because, as mentioned in the man page, bash will perform the brace expansion on each word after splitting a command line into words.
So, that command line will be first split into {chown
, httpd,chmod
and 700}
, and then, since {chown
is not a valid brace expansion pattern, it will be left as is and bash will try to run a command with that name.
This is the quote from the manpage:
Expansion is performed on the command line after it has been split into words. There are seven kinds of expansion performed: brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, word splitting, and pathname expansion.
Notice the order, which is different from other shells (in zsh
, the brace expansion will be performed after the arithmetic expansion, and the extra word splitting won't be performed at all).
The following will print 1 2
in zsh
or ksh
, and x y
in bash
:
f=; f1=x; f2=y; echo $f{1,2}
a
variable contains the string x y
, then a command line like echo $a
will be 1st split into echo
and $a
, then $a
will be expanded into x y
, and then split again into x
and y
, giving echo
, x
and y
as separate arguments. The latter step will be done using the value of IFS
( not necessarily containing spaces) and does not happen in zsh
.
–
Feb 11 '19 at 13:39
The text after the ‘=’ in each variable assignment undergoes tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal before being assigned to the variable
from bash reference guide.
– LRDPRDX
Jun 04 '20 at 13:06
Other answers have explained why the brace expansion doesn't work. Ignoring that question for a moment, you probably want to avoid repeating the filename, and there are other ways to do that. Either assign the file name to a variable, or use the $_
special variable (it contains the last shell word of the previous command):
f="some long and ugly filename"
chown httpd "$f"
chmod 700 "$f"
or
chown httpd "some long and ugly filename"
chmod 700 "$_"
tee
+xargs
can help if you have a very long path which you don't want to repeat each time:tee >(xargs chown httpd) >(xargs chmod 700) <<< /dir/test1
. – jimmij Feb 11 '19 at 12:53