doc/til_postgres.txt: Update tracklog import command.
[gpstools.git] / gpst-file
blob691c6930ce97df8e6572ee63b411c64a84c1663d
1 #!/usr/bin/perl -w
3 #=======================================================================
4 # gpst-file
5 # File ID: 86736de4-00a1-11de-acc1-000475e441b9
6 # Generate TAB streams of files with modification time for use with COPY
7 # in Postgres
9 # Character set: UTF-8
10 # ©opyleft 2009– Øyvind A. Holm <sunny@sunbase.org>
11 # License: GNU General Public License version 3 or later, see end of
12 # file for legal stuff.
13 #=======================================================================
15 use strict;
16 use Getopt::Long;
18 BEGIN {
19 push(@INC, "$ENV{'HOME'}/bin/src/gpstools");
20 our @version_array;
23 use GPST;
24 use GPSTxml;
26 $| = 1;
28 our $Debug = 0;
29 our $NA = '\N';
30 our %Std = (
32 'output-format' => 'pgtab',
33 'timezone' => '',
36 our %Opt = (
38 'author' => '',
39 'debug' => 0,
40 'description' => '',
41 'help' => 0,
42 'output-format' => $Std{'output-format'},
43 'strip-whitespace' => 0,
44 'timezone' => $Std{'timezone'},
45 'verbose' => 0,
46 'version' => 0,
50 our $progname = $0;
51 $progname =~ s/^.*\/(.*?)$/$1/;
52 our $VERSION = "0.00";
54 Getopt::Long::Configure("bundling");
55 GetOptions(
57 "author|a=s" => \$Opt{'author'},
58 "debug" => \$Opt{'debug'},
59 "description|d=s" => \$Opt{'description'},
60 "help|h" => \$Opt{'help'},
61 "output-format|o=s" => \$Opt{'output-format'},
62 "strip-whitespace|w" => \$Opt{'strip-whitespace'},
63 "timezone|T=s" => \$Opt{'timezone'},
64 "verbose|v+" => \$Opt{'verbose'},
65 "version" => \$Opt{'version'},
67 ) || die("$progname: Option error. Use -h for help.\n");
69 $Opt{'debug'} && ($Debug = 1);
70 $Opt{'help'} && usage(0);
71 if ($Opt{'version'}) {
72 print_version();
73 exit(0);
76 $GPST::Spc = $Opt{'strip-whitespace'} ? "" : " ";
77 my $Spc = $GPST::Spc; # FIXME
78 my $tz_str = "";
79 if (length($Opt{'timezone'})) {
80 if ($Opt{'timezone'} =~ /^[\+\-][0-2][0-9]{3}$/) {
81 $tz_str = $Opt{'timezone'};
82 } elsif ($Opt{'timezone'} =~ /^z$/i) {
83 $tz_str = $Opt{'timezone'};
84 } elsif ($Opt{'timezone'} =~ /^[a-z]+$/i) {
85 $tz_str = " $Opt{'timezone'}";
86 } else {
87 die("$progname: $Opt{'timezone'}: Invalid time zone\n");
89 $tz_str = uc($tz_str);
92 if ($Opt{'output-format'} eq "xml") {
93 print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<gpstfile>\n");
96 if ($#ARGV < 0) {
97 while (<>) {
98 chomp();
99 print_entry($_);
101 } else {
102 for my $fname (@ARGV) {
103 print_entry($fname);
107 if ($Opt{'output-format'} eq "xml") {
108 print("</gpstfile>\n");
111 sub print_entry {
112 # {{{
113 my $filename = shift;
114 my $Retval = 0;
115 my ($date, $coor) =
116 ('', '');
117 D("filename = '$filename'");
118 if (my @stat_array = stat($filename)) {
119 my @TA = localtime($stat_array[9]);
120 $date = sprintf("%04u-%02u-%02uT%02u:%02u:%02u%s",
121 $TA[5]+1900, $TA[4]+1, $TA[3], $TA[2], $TA[1], $TA[0], $tz_str);
122 D("tz_str = '$tz_str'");
123 $filename =~ s/^.*\/(.*?)$/$1/;
124 my $Output = "";
125 if ($Opt{'output-format'} eq "xml") {
126 if (length("$filename$date")) {
127 $Output = join("",
128 "$Spc$Spc<file>\n",
129 length($filename)
130 ? sprintf("$Spc$Spc$Spc$Spc<filename>%s</filename>\n",
131 txt_to_xml($filename))
132 : "",
133 length($date)
134 ? sprintf("$Spc$Spc$Spc$Spc<date>%s</date>\n",
135 txt_to_xml($date))
136 : "",
137 length($Opt{'description'})
138 ? sprintf("$Spc$Spc$Spc$Spc<desc>%s</desc>\n",
139 txt_to_xml($Opt{'description'}))
140 : "",
141 length($Opt{'author'})
142 ? sprintf("$Spc$Spc$Spc$Spc<author>%s</author>\n",
143 txt_to_xml($Opt{'author'}))
144 : "",
145 "$Spc$Spc</file>\n",
148 } elsif ($Opt{'output-format'} eq "pgtab") {
149 # Version information {{{
150 # Version 1:
151 # "1" \t
152 # date \t
153 # "(lat,lon)"-coordinates \t
154 # description \t
155 # filename \t
156 # author \n
157 # }}}
158 $Output = pgtab_entry(
159 1, # Version number
160 $date,
161 $coor,
162 $Opt{'description'},
163 $filename,
164 $Opt{'author'}
166 } else {
167 die("$progname: $Opt{'output-format'}: Unknown output format\n");
169 print($Output);
170 $Opt{'verbose'} && print(STDERR $Output);
171 } else {
172 warn("$progname: $filename: Cannot stat file: $!\n");
174 return($Retval);
175 # }}}
176 } # print_entry()
178 sub pgtab_entry {
179 # {{{
180 my ($Version, $Date, $Coor, $Descr, $Filename, $Author) = @_;
181 defined($Date) || ($Date = $NA);
182 defined($Coor) || ($Coor = $NA);
183 defined($Descr) || ($Descr = $NA);
184 defined($Filename) || ($Filename = $NA);
185 defined($Author) || ($Author = $NA);
186 my $Retval = "";
187 if ($Version == 1) {
188 $Retval = join("\t",
189 1, # Version number
190 postgresql_copy_safe($Date),
191 length($Coor)
192 ? postgresql_copy_safe($Coor)
193 : $NA,
194 length($Opt{'description'})
195 ? postgresql_copy_safe($Opt{'description'})
196 : $NA,
197 length($Filename)
198 ? postgresql_copy_safe($Filename)
199 : $NA,
200 length($Opt{'author'})
201 ? postgresql_copy_safe($Opt{'author'})
202 : $NA
203 ) . "\n";
205 return($Retval);
206 # }}}
207 } # pgtab_entry()
209 sub print_version {
210 # Print program version {{{
211 print("$progname v$VERSION\n");
212 # }}}
213 } # print_version()
215 sub usage {
216 # Send the help message to stdout {{{
217 my $Retval = shift;
219 if ($Opt{'verbose'}) {
220 print("\n");
221 print_version();
223 print(<<END);
225 Usage: $progname [options] [file [files [...]]]
227 Generate TAB streams with filenames and file modification time for use
228 with PostgreSQL’s COPY command. If no filenames are specified on the
229 command line, file names are read from stdin.
231 Options:
233 -a, --author x
234 Specify author of file.
235 -d, --description x
236 Specify description for file.
237 -h, --help
238 Show this help.
239 -v, --verbose
240 Increase level of verbosity. Can be repeated.
241 -o x, --output-format x
242 Create output of type x:
244 pgtab
245 Default: "$Std{'output-format'}".
246 -T X, --timezone X
247 Prepend X as timezone to the date. Valid formats:
248 UTC offset
249 A '+' or '-' followed by a four-digit number (HHMM) which
250 indicates the offset relative to UTC. Examples:
251 +0000
252 -1600
253 +0630
254 Time zone abbreviation. Examples:
258 -w, --strip-whitespace
259 Strip all unnecessary whitespace.
260 --version
261 Print version information.
262 --debug
263 Print debugging messages.
266 exit($Retval);
267 # }}}
268 } # usage()
270 sub msg {
271 # Print a status message to stderr based on verbosity level {{{
272 my ($verbose_level, $Txt) = @_;
274 if ($Opt{'verbose'} >= $verbose_level) {
275 print(STDERR "$progname: $Txt\n");
277 # }}}
278 } # msg()
280 sub D {
281 # Print a debugging message {{{
282 $Debug || return;
283 my @call_info = caller;
284 chomp(my $Txt = shift);
285 my $File = $call_info[1];
286 $File =~ s#\\#/#g;
287 $File =~ s#^.*/(.*?)$#$1#;
288 print(STDERR "$File:$call_info[2] $$ $Txt\n");
289 return("");
290 # }}}
291 } # D()
293 __END__
295 # Plain Old Documentation (POD) {{{
297 =pod
299 =head1 NAME
303 =head1 SYNOPSIS
305 [options] [file [files [...]]]
307 =head1 DESCRIPTION
311 =head1 OPTIONS
313 =over 4
315 =item B<-h>, B<--help>
317 Print a brief help summary.
319 =item B<-v>, B<--verbose>
321 Increase level of verbosity. Can be repeated.
323 =item B<--version>
325 Print version information.
327 =item B<--debug>
329 Print debugging messages.
331 =back
333 =head1 BUGS
337 =head1 AUTHOR
339 Made by Øyvind A. Holm S<E<lt>sunny@sunbase.orgE<gt>>.
341 =head1 COPYRIGHT
343 Copyleft © Øyvind A. Holm E<lt>sunny@sunbase.orgE<gt>
344 This is free software; see the file F<COPYING> for legalese stuff.
346 =head1 LICENCE
348 This program is free software: you can redistribute it and/or modify it
349 under the terms of the GNU General Public License as published by the
350 Free Software Foundation, either version 3 of the License, or (at your
351 option) any later version.
353 This program is distributed in the hope that it will be useful, but
354 WITHOUT ANY WARRANTY; without even the implied warranty of
355 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
356 See the GNU General Public License for more details.
358 You should have received a copy of the GNU General Public License along
359 with this program.
360 If not, see L<http://www.gnu.org/licenses/>.
362 =head1 SEE ALSO
364 =cut
366 # }}}
368 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :