+ if close then close_in in_chan
+ ) files
+
+let cmd_set_columns ~input_sep ~output_sep ~chan cols files =
+ (* Avoid loading the whole file into memory. *)
+ let f row =
+ let csv = [row] in
+ let csv = set_columns cols csv in
+ save_out ~separator:output_sep chan csv
+ in
+ List.iter (
+ fun filename ->
+ let in_chan, close =
+ match filename with
+ | "-" -> stdin, false
+ | filename -> open_in filename, true in
+ load_rows ~separator:input_sep f in_chan;
+ if close then close_in in_chan
+ ) files
+
+let cmd_set_rows ~input_sep ~output_sep ~chan rows files =
+ let csv = List.concat (List.map (load ~separator:input_sep) files) in
+ let csv = set_rows rows csv in
+ save_out ~separator:output_sep chan csv
+
+let cmd_head ~input_sep ~output_sep ~chan rows files =
+ (* Avoid loading the whole file into memory, or even loading
+ * later files.
+ *)
+ let nr_rows = ref rows in
+ let f row =
+ if !nr_rows > 0 then (
+ decr nr_rows;
+ save_out ~separator:output_sep chan [row]
+ )
+ in
+ List.iter (
+ fun filename ->
+ if !nr_rows > 0 then (
+ let in_chan, close =
+ match filename with
+ | "-" -> stdin, false
+ | filename -> open_in filename, true in
+ load_rows ~separator:input_sep f in_chan;
+ if close then close_in in_chan
+ )
+ ) files
+
+let cmd_drop ~input_sep ~output_sep ~chan rows files =
+ (* Avoid loading the whole file into memory. *)
+ let nr_rows = ref rows in
+ let f row =
+ if !nr_rows = 0 then
+ save_out ~separator:output_sep chan [row]
+ else
+ decr nr_rows
+ in
+ List.iter (
+ fun filename ->
+ let in_chan, close =
+ match filename with
+ | "-" -> stdin, false
+ | filename -> open_in filename, true in
+ load_rows ~separator:input_sep f in_chan;
+ if close then close_in in_chan