@@ -28,10 +28,10 @@ DEALINGS IN THE SOFTWARE. */
28
28
29
29
#include <htslib/hts.h>
30
30
#include <htslib/sam.h>
31
+ #include <htslib/hfile.h>
31
32
#include <htslib/khash.h>
32
33
#include <stdlib.h>
33
34
#include <stdio.h>
34
- #define __STDC_FORMAT_MACROS
35
35
#include <inttypes.h>
36
36
#include <unistd.h>
37
37
#include <getopt.h>
@@ -44,63 +44,97 @@ DEALINGS IN THE SOFTWARE. */
44
44
static void index_usage (FILE * fp )
45
45
{
46
46
fprintf (fp ,
47
- "Usage: samtools index [-bc] [-m INT] <in.bam> [out.index]\n"
47
+ "Usage: samtools index -M [-bc] [-m INT] <in1.bam> <in2.bam>...\n"
48
+ " or: samtools index [-bc] [-m INT] <in.bam> [out.index]\n"
48
49
"Options:\n"
49
50
" -b Generate BAI-format index for BAM files [default]\n"
50
51
" -c Generate CSI-format index for BAM files\n"
51
52
" -m INT Set minimum interval size for CSI indices to 2^INT [%d]\n"
53
+ " -M Interpret all filename arguments as files to be indexed\n"
54
+ " -o FILE Write index to FILE [alternative to <out.index> as an argument]\n"
52
55
" -@ INT Sets the number of threads [none]\n" , BAM_LIDX_SHIFT );
53
56
}
54
57
58
+ // Returns 1 if the file does not exist or can be positively
59
+ // identified as an index file.
60
+ static int nonexistent_or_index (const char * fn )
61
+ {
62
+ int ret1 , ret2 ;
63
+ htsFormat fmt ;
64
+ hFILE * fp = hopen (fn , "r" );
65
+ if (fp == NULL ) return 1 ;
66
+
67
+ ret1 = hts_detect_format2 (fp , fn , & fmt );
68
+ ret2 = hclose (fp );
69
+ if (ret1 < 0 || ret2 < 0 ) return 0 ;
70
+
71
+ return fmt .category == index_file ;
72
+ }
73
+
55
74
int bam_index (int argc , char * argv [])
56
75
{
57
76
int csi = 0 ;
58
77
int min_shift = BAM_LIDX_SHIFT ;
78
+ int multiple = 0 ;
59
79
int n_threads = 0 ;
60
- int c , ret ;
80
+ int n_files , c , i , ret ;
81
+ const char * fn_idx = NULL ;
61
82
62
- while ((c = getopt (argc , argv , "bcm:@:" )) >= 0 )
83
+ while ((c = getopt (argc , argv , "bcm:Mo: @:" )) >= 0 )
63
84
switch (c ) {
64
85
case 'b' : csi = 0 ; break ;
65
86
case 'c' : csi = 1 ; break ;
66
87
case 'm' : csi = 1 ; min_shift = atoi (optarg ); break ;
88
+ case 'M' : multiple = 1 ; break ;
89
+ case 'o' : fn_idx = optarg ; break ;
67
90
case '@' : n_threads = atoi (optarg ); break ;
68
91
default :
69
92
index_usage (stderr );
70
93
return 1 ;
71
94
}
72
95
73
- if (optind == argc ) {
74
- index_usage (stdout );
75
- return 1 ;
76
- }
96
+ n_files = argc - optind ;
77
97
78
- ret = sam_index_build3 (argv [optind ], argv [optind + 1 ], csi ? min_shift : 0 , n_threads );
79
- switch (ret ) {
80
- case 0 :
98
+ if (n_files == 0 ) {
99
+ index_usage (stdout );
81
100
return 0 ;
101
+ }
82
102
83
- case -2 :
84
- print_error_errno ("index" , "failed to open \"%s\"" , argv [optind ]);
85
- break ;
103
+ // Handle legacy synopsis
104
+ if (n_files == 2 && !fn_idx && nonexistent_or_index (argv [optind + 1 ])) {
105
+ n_files = 1 ;
106
+ fn_idx = argv [optind + 1 ];
107
+ }
86
108
87
- case -3 :
88
- print_error ("index" , "\"%s\" is in a format that cannot be usefully indexed" , argv [optind ]);
89
- break ;
109
+ if (n_files > 1 && !multiple ) {
110
+ print_error ("index" , "use -M to enable indexing more than one alignment file" );
111
+ return EXIT_FAILURE ;
112
+ }
90
113
91
- case -4 :
92
- if (argv [optind + 1 ])
93
- print_error ("index" , "failed to create or write index \"%s\"" , argv [optind + 1 ]);
94
- else
95
- print_error ("index" , "failed to create or write index" );
96
- break ;
114
+ if (fn_idx && n_files > 1 ) {
115
+ // TODO In future we may allow %* placeholders or similar
116
+ print_error ("index" , "can't use -o with multiple input alignment files" );
117
+ return EXIT_FAILURE ;
118
+ }
97
119
98
- default :
99
- print_error_errno ("index" , "failed to create index for \"%s\"" , argv [optind ]);
100
- break ;
120
+ for (i = optind ; i < optind + n_files ; i ++ ) {
121
+ ret = sam_index_build3 (argv [i ], fn_idx , csi ? min_shift : 0 , n_threads );
122
+ if (ret < 0 ) {
123
+ if (ret == -2 )
124
+ print_error_errno ("index" , "failed to open \"%s\"" , argv [i ]);
125
+ else if (ret == -3 )
126
+ print_error ("index" , "\"%s\" is in a format that cannot be usefully indexed" , argv [i ]);
127
+ else if (ret == -4 && fn_idx )
128
+ print_error ("index" , "failed to create or write index \"%s\"" , fn_idx );
129
+ else if (ret == -4 )
130
+ print_error ("index" , "failed to create or write index" );
131
+ else
132
+ print_error_errno ("index" , "failed to create index for \"%s\"" , argv [i ]);
133
+ return EXIT_FAILURE ;
134
+ }
101
135
}
102
136
103
- return EXIT_FAILURE ;
137
+ return EXIT_SUCCESS ;
104
138
}
105
139
106
140
/*
0 commit comments