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?)

muru
  • 72,889
syss
  • 701
  • 1
    use cat file.[123] >file – mikeserv Nov 17 '15 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 '15 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 '15 at 10:51
  • @AlecTeal it seems to be that I mixed this up with another situation I had once – syss Nov 24 '15 at 11:16
  • @mikeserv, since that method isn't mentioned in any of the posted answers, would you mind adding it as an answer and explaining it? – Wildcard Mar 05 '16 at 08:38
  • @Wildcard - it isn't exactly relevant to the question, though... – mikeserv Mar 15 '16 at 12: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 '16 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 '16 at 13:12

3 Answers3

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

cuonglm
  • 153,898
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.

terdon
  • 242,166
  • 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 '15 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 '15 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 '15 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 '15 at 15:10
  • Won't adding .txt solve the issue with file.*? – Ismael Miguel Nov 18 '15 at 01:59
  • @IsmaelMiguel what issue with file.*? – terdon Nov 18 '15 at 10:32
  • cat: file.txt: input file is output file. – Ismael Miguel Nov 18 '15 at 12:08
  • @IsmaelMiguel oh, yes, of course that will fix it since the glob isn't matching the output file. The point was about those cases where the glob does match the output file. – terdon Nov 18 '15 at 12:13
  • Gotta ask, how does cat know the input file is the output file? (because > thing is telling the shell "spew stdout over there") – Alec Teal Nov 24 '15 at 19:47
  • @AlecTeal cat doesn't, this is all done by the shell. Shell commands are read right to left, so when you cat file.* > file.txt, file.txt is created first and then the file.* is expanded. So the shell complains about its input file being its output file. – terdon Nov 24 '15 at 20:58
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

cristi
  • 561