| OLD | NEW |
| 1 # -*- coding: utf-8 -*- |
| 1 # Copyright 2011 Google Inc. All Rights Reserved. | 2 # Copyright 2011 Google Inc. All Rights Reserved. |
| 2 # Copyright 2011, Nexenta Systems Inc. | 3 # Copyright 2011, Nexenta Systems Inc. |
| 3 # | 4 # |
| 4 # Licensed under the Apache License, Version 2.0 (the "License"); | 5 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 # you may not use this file except in compliance with the License. | 6 # you may not use this file except in compliance with the License. |
| 6 # You may obtain a copy of the License at | 7 # You may obtain a copy of the License at |
| 7 # | 8 # |
| 8 # http://www.apache.org/licenses/LICENSE-2.0 | 9 # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 # | 10 # |
| 10 # Unless required by applicable law or agreed to in writing, software | 11 # Unless required by applicable law or agreed to in writing, software |
| 11 # distributed under the License is distributed on an "AS IS" BASIS, | 12 # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 # See the License for the specific language governing permissions and | 14 # See the License for the specific language governing permissions and |
| 14 # limitations under the License. | 15 # limitations under the License. |
| 16 """Implementation of Unix-like cat command for cloud storage providers.""" |
| 17 |
| 18 from __future__ import absolute_import |
| 15 | 19 |
| 16 import re | 20 import re |
| 17 import sys | |
| 18 | 21 |
| 22 from gslib.cat_helper import CatHelper |
| 19 from gslib.command import Command | 23 from gslib.command import Command |
| 20 from gslib.command import COMMAND_NAME | 24 from gslib.cs_api_map import ApiSelector |
| 21 from gslib.command import COMMAND_NAME_ALIASES | |
| 22 from gslib.command import FILE_URIS_OK | |
| 23 from gslib.command import MAX_ARGS | |
| 24 from gslib.command import MIN_ARGS | |
| 25 from gslib.command import PROVIDER_URIS_OK | |
| 26 from gslib.command import SUPPORTED_SUB_ARGS | |
| 27 from gslib.command import URIS_START_ARG | |
| 28 from gslib.exception import CommandException | 25 from gslib.exception import CommandException |
| 29 from gslib.help_provider import HELP_NAME | |
| 30 from gslib.help_provider import HELP_NAME_ALIASES | |
| 31 from gslib.help_provider import HELP_ONE_LINE_SUMMARY | |
| 32 from gslib.help_provider import HELP_TEXT | |
| 33 from gslib.help_provider import HelpType | |
| 34 from gslib.help_provider import HELP_TYPE | |
| 35 from gslib.util import NO_MAX | 26 from gslib.util import NO_MAX |
| 36 from gslib.wildcard_iterator import ContainsWildcard | |
| 37 | 27 |
| 38 _detailed_help_text = (""" | 28 _DETAILED_HELP_TEXT = (""" |
| 39 <B>SYNOPSIS</B> | 29 <B>SYNOPSIS</B> |
| 40 gsutil cat [-h] uri... | 30 gsutil cat [-h] url... |
| 41 | 31 |
| 42 | 32 |
| 43 <B>DESCRIPTION</B> | 33 <B>DESCRIPTION</B> |
| 44 The cat command outputs the contents of one or more URIs to stdout. | 34 The cat command outputs the contents of one or more URLs to stdout. |
| 45 It is equivalent to doing: | 35 It is equivalent to doing: |
| 46 | 36 |
| 47 gsutil cp uri... - | 37 gsutil cp url... - |
| 48 | 38 |
| 49 (The final '-' causes gsutil to stream the output to stdout.) | 39 (The final '-' causes gsutil to stream the output to stdout.) |
| 50 | 40 |
| 51 | 41 |
| 52 <B>OPTIONS</B> | 42 <B>OPTIONS</B> |
| 53 -h Prints short header for each object. For example: | 43 -h Prints short header for each object. For example: |
| 54 | 44 |
| 55 gsutil cat -h gs://bucket/meeting_notes/2012_Feb/*.txt | 45 gsutil cat -h gs://bucket/meeting_notes/2012_Feb/*.txt |
| 56 | 46 |
| 57 This would print a header with the object name before the contents | 47 This would print a header with the object name before the contents |
| (...skipping 17 matching lines...) Expand all Loading... |
| 75 | 65 |
| 76 gsutil cat -r -5 gs://bucket/object | 66 gsutil cat -r -5 gs://bucket/object |
| 77 | 67 |
| 78 returns the final 5 bytes of the object. | 68 returns the final 5 bytes of the object. |
| 79 """) | 69 """) |
| 80 | 70 |
| 81 | 71 |
| 82 class CatCommand(Command): | 72 class CatCommand(Command): |
| 83 """Implementation of gsutil cat command.""" | 73 """Implementation of gsutil cat command.""" |
| 84 | 74 |
| 85 # Command specification (processed by parent class). | 75 # Command specification. See base class for documentation. |
| 86 command_spec = { | 76 command_spec = Command.CreateCommandSpec( |
| 87 # Name of command. | 77 'cat', |
| 88 COMMAND_NAME : 'cat', | 78 command_name_aliases=[], |
| 89 # List of command name aliases. | 79 min_args=0, |
| 90 COMMAND_NAME_ALIASES : [], | 80 max_args=NO_MAX, |
| 91 # Min number of args required by this command. | 81 supported_sub_args='hr:', |
| 92 MIN_ARGS : 0, | 82 file_url_ok=False, |
| 93 # Max number of args required by this command, or NO_MAX. | 83 provider_url_ok=False, |
| 94 MAX_ARGS : NO_MAX, | 84 urls_start_arg=0, |
| 95 # Getopt-style string specifying acceptable sub args. | 85 gs_api_support=[ApiSelector.XML, ApiSelector.JSON], |
| 96 SUPPORTED_SUB_ARGS : 'hvr:', | 86 gs_default_api=ApiSelector.JSON, |
| 97 # True if file URIs acceptable for this command. | 87 ) |
| 98 FILE_URIS_OK : False, | 88 # Help specification. See help_provider.py for documentation. |
| 99 # True if provider-only URIs acceptable for this command. | 89 help_spec = Command.HelpSpec( |
| 100 PROVIDER_URIS_OK : False, | 90 help_name='cat', |
| 101 # Index in args of first URI arg. | 91 help_name_aliases=[], |
| 102 URIS_START_ARG : 0, | 92 help_type='command_help', |
| 103 } | 93 help_one_line_summary='Concatenate object content to stdout', |
| 104 help_spec = { | 94 help_text=_DETAILED_HELP_TEXT, |
| 105 # Name of command or auxiliary help info for which this help applies. | 95 subcommand_help_text={}, |
| 106 HELP_NAME : 'cat', | 96 ) |
| 107 # List of help name aliases. | |
| 108 HELP_NAME_ALIASES : [], | |
| 109 # Type of help: | |
| 110 HELP_TYPE : HelpType.COMMAND_HELP, | |
| 111 # One line summary of this help. | |
| 112 HELP_ONE_LINE_SUMMARY : 'Concatenate object content to stdout', | |
| 113 # The full help text. | |
| 114 HELP_TEXT : _detailed_help_text, | |
| 115 } | |
| 116 | |
| 117 def _UriIterator(self, uri_str): | |
| 118 # Generator that returns URI(s) for uri_str. If uri_str is a wildcard we | |
| 119 # iterate over matches, else we return a single URI. | |
| 120 if not ContainsWildcard(uri_str): | |
| 121 yield self.suri_builder.StorageUri(uri_str) | |
| 122 else: | |
| 123 for uri in self.WildcardIterator(uri_str).IterUris(): | |
| 124 yield uri | |
| 125 | 97 |
| 126 # Command entry point. | 98 # Command entry point. |
| 127 def RunCommand(self): | 99 def RunCommand(self): |
| 100 """Command entry point for the cat command.""" |
| 128 show_header = False | 101 show_header = False |
| 129 request_range = None | 102 request_range = None |
| 103 start_byte = 0 |
| 104 end_byte = None |
| 130 if self.sub_opts: | 105 if self.sub_opts: |
| 131 for o, a in self.sub_opts: | 106 for o, a in self.sub_opts: |
| 132 if o == '-h': | 107 if o == '-h': |
| 133 show_header = True | 108 show_header = True |
| 134 elif o == '-r': | 109 elif o == '-r': |
| 135 request_range = a.strip() | 110 request_range = a.strip() |
| 136 if not re.match('^[0-9]+-[0-9]*$|^-[0-9]+$', request_range): | 111 range_matcher = re.compile( |
| 112 '^(?P<start>[0-9]+)-(?P<end>[0-9]*)$|^(?P<endslice>-[0-9]+)$') |
| 113 range_match = range_matcher.match(request_range) |
| 114 if not range_match: |
| 137 raise CommandException('Invalid range (%s)' % request_range) | 115 raise CommandException('Invalid range (%s)' % request_range) |
| 138 elif o == '-v': | 116 if range_match.group('start'): |
| 139 self.logger.info('WARNING: The %s -v option is no longer' | 117 start_byte = long(range_match.group('start')) |
| 140 ' needed, and will eventually be removed.\n' | 118 if range_match.group('end'): |
| 141 % self.command_name) | 119 end_byte = long(range_match.group('end')) |
| 120 if range_match.group('endslice'): |
| 121 start_byte = long(range_match.group('endslice')) |
| 142 | 122 |
| 143 printed_one = False | 123 return CatHelper(self).CatUrlStrings(self.args, |
| 144 # We manipulate the stdout so that all other data other than the Object | 124 show_header=show_header, |
| 145 # contents go to stderr. | 125 start_byte=start_byte, |
| 146 cat_outfd = sys.stdout | 126 end_byte=end_byte) |
| 147 sys.stdout = sys.stderr | |
| 148 did_some_work = False | |
| 149 | |
| 150 for uri_str in self.args: | |
| 151 for uri in self._UriIterator(uri_str): | |
| 152 if not uri.names_object(): | |
| 153 raise CommandException('"%s" command must specify objects.' % | |
| 154 self.command_name) | |
| 155 did_some_work = True | |
| 156 if show_header: | |
| 157 if printed_one: | |
| 158 print | |
| 159 print '==> %s <==' % uri.__str__() | |
| 160 printed_one = True | |
| 161 key = uri.get_key(False, self.headers) | |
| 162 headers = self.headers.copy() | |
| 163 if request_range: | |
| 164 headers['range'] = 'bytes=%s' % str(request_range) | |
| 165 key.get_file(cat_outfd, headers) | |
| 166 sys.stdout = cat_outfd | |
| 167 if not did_some_work: | |
| 168 raise CommandException('No URIs matched') | |
| 169 | |
| 170 return 0 | |
| OLD | NEW |