Explain: {,} in cp or mv Bash Shell Commands

by on February 19, 2014 · 13 comments· LAST UPDATED February 21, 2014

in , ,

I often see commands as follows posted on blog or forums

cp /etc/httpd/httpd.{,.bakup}

OR

mv resume{z,}.doc

What is the purpose of {,} in Linux and Unix shell commands?

Tutorial details
DifficultyEasy (rss)
Root privilegesNo
RequirementsNone
Estimated completion time2m
{} is nothing but brace expansion and usually used to generate combinations. From the GNU/bash man page:

Brace expansion is a mechanism by which arbitrary strings may be generated. This mechanism is similar to filename expansion, but the file names generated need not exist. Patterns to be brace expanded take the form of an optional preamble, followed by either a series of comma-separated strings or a seqeunce expression between a pair of braces, followed by an optional postscript. The preamble is prefixed to each string contained within the braces, and the postscript is then appended to each resulting string, expanding left to right.

Open terminal and type the following command:

echo foo{1,2,3}.txt

Sample outputs:

foo1.txt foo2.txt foo3.txt

Try the following additonal examples to create arguments for commands and save typing time:

### I am using echo for demo purpose only ####
echo file.txt{,.bak}
echo file-{a..d}.txt
echo mkdir -p /apache-jail/{usr,bin,lib64,dev}
echo cp httpd.conf{,.backup}
echo mv delta.{txt,doc}
 

You can use brace expansion to copy file, rename/backup file, or create directories. In this traditional example, make a backup of a file named file1.txt to file2.txt.bak, type:

 
cp -v file1.txt file1.txt.bak
 

You can save time with brace expansion as follows:

 
cp -v file1.txt{,.bak}
 

Sample outputs:

file1.txt -> file1.txt.bak

See bash(1) command man page for more information.

TwitterFacebookGoogle+PDF versionFound an error/typo on this page? Help us!

{ 13 comments… read them below or add one }

1 tolli February 19, 2014 at 9:31 pm

“brace expansion only works with file names”
This is not true. For example:
$ echo a{b,c,d}
ab ac ad

The command “host -t a cyberciti.{biz,com}” expands to “host -t a cyberciti.biz cyberciti.com”. The problem is that the ‘host’ command only accepts one hostname argument. It use the last argument (“cyberciti.com”) as a DNS server to look up the hostname. (See the ‘host’ man page for more details) Since cyberciti.com is not a DNS server, it just hangs waiting for a response.

Reply

2 Nix Craft February 21, 2014 at 7:53 pm

The faq has been updated. I appreciate your feedback and post.

Reply

3 tolli February 21, 2014 at 9:12 pm

Thanks!
By the way, if you use xargs, you can use brace expansion with the ‘host’ command, like this:

$ echo cyberciti.{biz,com} | xargs -n 1 host -t a
cyberciti.biz has address 75.126.153.206
cyberciti.com has address 184.168.221.1

Reply

4 Farzan Jameel Mufti February 20, 2014 at 12:36 am

I can elaborate these expansions with examples.

echo {a,b}c prints ac bc notice the space in between
echo xyz{1,2}X prints xyz1X xyz2X
echo AB{a,b,c}.txt print ABa.txt ABb.txt ABc.txt
echo {a,b} prints a b

Now to your question:
cp /etc/httpd/httpd.{,.bakup}

So lets see expansion
cp /etc/httpd/httpd. /etc/httpd/httpd..bacup

In the above question, I think you need to get rid of the first dot, which doesn’t make sense.

It should be
cp /etc/httpd/httpd.conf{,.bkup}
Then it expands to
cp /etc/httpd/httpd.conf /etc/httpd.conf.bkup

Second question:
mv resume{z,}.doc
mv resumez.doc resume.doc
Changing the name from resumez.doc to resume.doc
HTH

Reply

5 laike9m February 20, 2014 at 1:28 pm

Didn’t know this!

Reply

6 Kevin Lausen February 20, 2014 at 10:43 pm

I watched a youtube video recently on the power of the command line where he did a command like:

mkdir -p {2013,2014,2015}:{Jan,Feb,March,April,Jun,Jul,Aug,Sep,Oct,Nov,Dec}:{Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday}

# for creating a backup tree, for monthly/daily backups for each year.

Reply

7 Farzan Jameel Mufti February 21, 2014 at 12:40 pm

It is got to be a slash instead of a colon. Like

mkdir -p {2013,2014,2015}/{Jan,Feb,March,April,Jun,Jul,Aug,Sep,Oct,Nov,Dec}/{Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday}

Reply

8 T.Mini February 22, 2014 at 9:05 am

A bad idea. A better way to manage backup dirs in monthly, weekly, and daily format. Let file system keep track of dates.

drwxr-xr-x 10 root root 4096 Feb 20 22:02 daily.0
drwxr-xr-x 10 root root 4096 Feb 19 22:02 daily.1
drwxr-xr-x 10 root root 4096 Feb 18 22:02 daily.2
drwxr-xr-x 10 root root 4096 Feb 17 22:02 daily.3
drwxr-xr-x 10 root root 4096 Feb 16 22:02 daily.4
drwxr-xr-x 10 root root 4096 Feb 15 22:02 daily.5
drwxr-xr-x 10 root root 4096 Feb 14 22:02 daily.6
drwxr-xr-x 10 root root 4096 Feb 22 02:02 hourly.0
drwxr-xr-x 10 root root 4096 Feb 22 00:02 hourly.1
drwxr-xr-x 10 root root 4096 Feb 21 06:02 hourly.10
drwxr-xr-x 10 root root 4096 Feb 21 04:02 hourly.11
drwxr-xr-x 10 root root 4096 Feb 21 22:02 hourly.2
drwxr-xr-x 10 root root 4096 Feb 21 20:02 hourly.3
drwxr-xr-x 10 root root 4096 Feb 21 18:02 hourly.4
drwxr-xr-x 10 root root 4096 Feb 21 16:02 hourly.5
drwxr-xr-x 10 root root 4096 Feb 21 14:02 hourly.6
drwxr-xr-x 10 root root 4096 Feb 21 12:02 hourly.7
drwxr-xr-x 10 root root 4096 Feb 21 10:02 hourly.8
drwxr-xr-x 10 root root 4096 Feb 21 08:02 hourly.9
drwxr-xr-x 10 root root 4096 Jan  4 22:02 monthly.0
drwxr-xr-x 10 root root 4096 Nov 30 22:02 monthly.1
drwxr-xr-x 10 root root 4096 Jan 26  2013 monthly.10
drwxr-xr-x 10 root root 4096 Dec 29  2012 monthly.11
drwxr-xr-x 10 root root 4096 Nov  2 22:02 monthly.2
drwxr-xr-x 10 root root 4096 Sep 28 22:02 monthly.3
drwxr-xr-x 10 root root 4096 Aug  3  2013 monthly.4
drwxr-xr-x 10 root root 4096 Jun 29  2013 monthly.5
drwxr-xr-x 10 root root 4096 Jun  1  2013 monthly.6
drwxr-xr-x 10 root root 4096 May  4  2013 monthly.7
drwxr-xr-x 10 root root 4096 Mar 30  2013 monthly.8
drwxr-xr-x 10 root root 4096 Mar  2  2013 monthly.9
drwxr-xr-x 10 root root 4096 Feb  8 22:02 weekly.0
drwxr-xr-x 10 root root 4096 Feb  1 22:02 weekly.1
drwxr-xr-x 10 root root 4096 Jan 25 22:02 weekly.2
drwxr-xr-x 10 root root 4096 Jan 18 22:02 weekly.3

Reply

9 Anthony June 20, 2014 at 1:51 am

T.Mini… Fist what Farzen is describing is a LONG term archiving structure (no deletions over VERY long periods of time). What you are describing is a rolling backup structure (only keep a minimal backup). They both have there uses.

Second… if you are going to use numbers… add leading zeros so they sort correctly.

Add leading zero if needed….
number=$(printf “%02d” $number)

Going back to Farzen’s post… If you are storing by date, best idea is to use the STANDARD ISO date format as it… sorts correctly!

date +’%Y-%m-%d’
2014-06-20

This format is (and mentioned) sortable, and does not have day-month order confict you get between american dates and british dates. That is, is the date “08-04-2000″, the 4th of august (American) or the 8th of July (Britich/Australian). Better to avoid any posible conflict by using a sortable international standard!

If you also need a time (to the second) say for logging data… add it like this…
The formating makes it obvious it is a date and time, and not just some ‘sequence number’. Note %R output a 24 hour clock whcih avoids AM-PM conflicts (something I have had to sort and it isn’t easy to do)

date +’%Y-%m-%d_%R:%S’
2014-06-20_11:42:07

Reply

10 magesh March 5, 2014 at 9:37 am

nice post

Reply

11 safeer March 6, 2014 at 2:16 pm

Was not aware of this..Nice

Reply

12 Andy March 23, 2014 at 3:14 pm

This is a nice post. I will definitely make use of this at work.

Reply

13 Anthony June 20, 2014 at 1:35 am

brace expansion is also good for enumerated arguments (typically numbers)

that is things like {1..5}

First it is limited to Bash > version 3.2
some versions of MacOSX did not have such an advanced bash installed!
If that is the case you may be better of using the “seq” command or function.

echo {5..15} # forward can be negative numebrs
5 6 7 8 9 10 11 12 13 14 15

echo {15..5} # reverse order
15 14 13 12 11 10 9 8 7 6 5

echo {5..15..2} # increment supported in BASH v4.0+
5 7 9 11 13 15

echo {a..d} # single letters (only single letters)
a b c d

echo {c..a}{A..C} # or letter sequence (multiple expand)
cA cB cC bA bB bC aA aB aC

echo {{1..5},{23..27}} # brace expandsions nest – two ranges of numbers
1 2 3 4 5 23 24 25 26 27

It can do simple formated numbers
echo {0007..11}
0007 0008 0009 0010 0011

printf “__%d__” {1..5}; echo “” # printf auto-loops multiple args
__1____2____3____4____5__

ASIDE: printf loops over its arguments, if arguments were left after doing the percent subsubstitions!

WARNING: you can not use variables in this syntax!

This for example it will NOT work … {1..$limit}
limit=5
echo {1..$limit}

Using eval substitution will work (painful though it is)…
echo $(eval echo {1..${MAX_SEGMENTS}})

You better of using a “for( ; ; )” loop!

Reply

Leave a Comment

Tagged as:

Previous Faq:

Next Faq: