17

Is there a difference between the sequences {1,2,3} and {1..3}?

For example if I have some files

file.1
file.2
file.3

and I want to cat them together is it safe to use cat file.{1..3} > file?

What I know is that cat file.*>file could cause problems because the shell can expand the files in a random way sometimes (I think this depends on the inodes, does it?)

8
  • 1
    use cat file.[123] >file
    – mikeserv
    Nov 17, 2015 at 14:58
  • 3
    The order of expansion of file.* is not dependent on the inodes. It always sorts them lexicographically, which could depend on your locate setting.
    – Barmar
    Nov 18, 2015 at 19:07
  • 1
    "depends on the inodes" sounds like a phase from one of the better researched criminal-minds-eqsue "computer" scenes.
    – Alec Teal
    Nov 24, 2015 at 10:51
  • 1
    @mikeserv, I believe I got it—it's a shell glob, so it only expands to files that actually exist, right? Vs. file.{1..3} which expands to all three whether or not they exist.
    – Wildcard
    Mar 15, 2016 at 13:10
  • 1
    @Wildcard - right, as long as at least one exists, that is. If not it expands not at all and cat errors with file.[123] not found or something very useful.
    – mikeserv
    Mar 15, 2016 at 13:12

3 Answers 3

18

{1..3} and {1,2,3} produce the same result, but with different way.

In general, {n1..n2} (which came first from zsh, bash and ksh copied it later) where n1 and n2 are integers produce all numbers between n1 and n2. While {x,y,z} produce three characters x, y and z.

In your case, you're safe to use cat file.{1..3} > file

Now, in case of cat file.*>file, you used the shell globbing, which produce all file name start with file. and the result will be sorted base on the collation order in current locale.

You are still safe, but not anymore when you have more than 10 files. {1..10} will give you 1 2 3 4 5 6 7 8 9 10. While with globbing, you will get 1 10 2 3 4 5 6 7 8 9

8

The difference is that one is a list and the other a sequence. {1,2,3} expands to three specific elements, 1,2, and 3. {1..3} expands to the list of numbers between one and three. In this particular case, they are the same and you can use either of the two. file.* will expand to all the files and directories in the current directory whose name starts with file.. If you only have file.1,file.2 and file.3 then that too is equivalent to the other two.

As for its causing problems, I don't see why. You might be thinking of

$ cat file.* > file.txt
cat: file.txt: input file is output file

That, however, is a completely different issue. The only other problem I can think of is that your shell might not list the files in the correct order. For example:

$ touch file1 file11 file2
$ echo file*
file1 file11 file2

To solve that, you can use zsh instead of bash (see here for details):

% echo f*(n)
file1 file2 file11

In general, the three approaches are not the same. It depends on what you want to do. In those cases where the three return the same output then, yes, you can use any of them. It makes no difference. All of these expansions are done by the shell and happen before they are passed to whatever command uses them.

10
  • wouldn't there be a problem with * if I had more or equal 10 files, if I depend on the right order?
    – syss
    Nov 17, 2015 at 14:40
  • 1
    @syss no. It would be a problem if you had more than ARG_MAX files but that will be way, way more than 10.
    – terdon
    Nov 17, 2015 at 14:41
  • 1
    @terdon He was asking if they'll appear in numerical order (i.e. not "1, 10, 2"), not if they'll overflow the argument array.
    – Random832
    Nov 17, 2015 at 15:08
  • 3
    @terdon I think @syss is right that the output of cat * is not well defined. The output depends on the shell and the environment. See Sebastian's comment.
    – Marco
    Nov 17, 2015 at 15:10
  • Won't adding .txt solve the issue with file.*? Nov 18, 2015 at 1:59
6

They are the same, but it depends on bash version you have installed if they are available.

From this page:

{xxx,yyy,zzz,...} probably in all bash versions

{a..z} introduced in bash 3

{<START>..<END>..<INCR>} new in bash 4

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .