Updated device commmands, Update use of \ in CSV files

This commit is contained in:
Ross Scroggs
2023-12-01 18:04:18 -08:00
parent b0f05c2dea
commit a64d6f1215
20 changed files with 297 additions and 86 deletions

View File

@ -69,13 +69,13 @@ gam redirect stdout ./NewStudents.out redirect stderr ./NewStudents.err tbatch N
## CSV files ## CSV files
``` ```
gam csv <FileName>|-|(gsheet <UserGoogleSheet>)|(gdoc <UserGoogleDoc>) [charset <Charset>] [warnifnodata] gam csv <FileName>|-|(gsheet <UserGoogleSheet>)|(gdoc <UserGoogleDoc>) [charset <Charset>] [warnifnodata]
[columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>]
(matchfield|skipfield <FieldName> <RegularExpression>)* [showcmds [<Boolean>]] (matchfield|skipfield <FieldName> <RegularExpression>)* [showcmds [<Boolean>]]
[maxrows <Integer>] [maxrows <Integer>]
gam <GAMArgumentList> gam <GAMArgumentList>
gam loop <FileName>|-|(gsheet <UserGoogleSheet>)|(gdoc <UserGoogleDoc>) [charset <Charset>] [warnifnodata] gam loop <FileName>|-|(gsheet <UserGoogleSheet>)|(gdoc <UserGoogleDoc>) [charset <Charset>] [warnifnodata]
[columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>]
(matchfield|skipfield <FieldName> <RegularExpression>)* [showcmds [<Boolean>]] (matchfield|skipfield <FieldName> <RegularExpression>)* [showcmds [<Boolean>]]
[maxrows <Integer>] [maxrows <Integer>]
gam <GAMArgumentList> gam <GAMArgumentList>
@ -87,6 +87,7 @@ gam loop <FileName>|-|(gsheet <UserGoogleSheet>)|(gdoc <UserGoogleDoc>) [charset
* `gsheet <UserGoogleSheet>` - A Google Sheet and the one or more columns that contain data * `gsheet <UserGoogleSheet>` - A Google Sheet and the one or more columns that contain data
* `gdoc <UserGoogleDoc>` - A Google Doc and the one or more columns that contain data * `gdoc <UserGoogleDoc>` - A Google Doc and the one or more columns that contain data
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used * `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `noescapechar <Boolean>` - Should `\` be ignored as an escape character; if not specified, the value of `csv_input_no_escape_char` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used * `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings. * `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings.
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected * `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected

View File

@ -0,0 +1,94 @@
# CSV Special Characters
- [Python CSV documentation](https://docs.python.org/3/library/csv.html#dialects-and-formatting-parameters)
## Python variables that control CSV file reading/writing:
```
Dialect.delimiter
A one-character string used to separate fields.
It defaults to ','.
Dialect.doublequote
Controls how instances of quotechar appearing inside a field should themselves be quoted.
When True, the character is doubled. When False, the escapechar is used as a prefix to the quotechar.
It defaults to True.
Dialect.escapechar
A one-character string used by the writer to escape the delimiter if quoting is set to QUOTE_NONE and the quotechar if doublequote is False.
On reading, the escapechar removes any special meaning from the following character.
It defaults to None, which disables escaping.
Dialect.lineterminator
The string used to terminate lines produced by the writer.
It defaults to '\r\n'.
The reader is hard-coded to recognise either '\r' or '\n' as end-of-line, and ignores lineterminator.
Dialect.quotechar
A one-character string used to quote fields containing special characters, such as the delimiter or quotechar, or which contain new-line characters.
It defaults to '"'.
Dialect.quoting
Controls when quotes should be generated by the writer and recognised by the reader. It can take on any of the QUOTE_* constants (see section Module Contents).
It defaults to QUOTE_MINIMAL.
```
## GAM variables that control CSV file reading/writing:
```
csv_input_column_delimiter = , - Dialect.delimiter
csv_input_no_escape_char = true - Dialect.escapechar is set to None if true, '\' if false
csv_input_quote_char = " - Dialect.quotechar
csv_output_column_delimiter = , - Dialect.delimiter
csv_output_no_escape_char = false - Dialect.escapechar is set to None if true, '\' if false
csv_output_line_terminator = lf - Dialect.lineterminator
csv_output_quote_char = " - Dialect.quotechar
todrive_no_escape_char = true - Dialect.escapechar is set to None if true, '\' if false
```
GAM sets Dialect.doublequote to true and Dialect.quoting to QUOTE_MINIMAL; there are no variables to change these values.
## Examples
### Local file, default settings
With these settings, here are examples of how field values are mapped on output to a local file:
```
csv_output_column_delimiter = ,
csv_output_no_escape_char = false
csv_output_quote_char = "
```
| Input | Output |
|-------|--------|
| abc def | abc def |
| abc,def | "abc,def" |
| abc"def | "abc""def" |
| abc\def | abc\\\\def |
### Local file, modified settings
With these settings, here are examples of how field values are mapped on output to a local file:
```
csv_output_column_delimiter = ,
csv_output_no_escape_char = true
csv_output_quote_char = "
```
| Input | Output |
|-------|--------|
| abc def | abc def |
| abc,def | "abc,def" |
| abc"def | "abc""def" |
| abc\def | abc\def |
### todrive, default settings
With these settings, here are examples of how field values are mapped on output to todrive
```
csv_output_column_delimiter = ,
todrive_no_escape_char = true
csv_output_quote_char = "
```
| Input | Output |
|-------|--------|
| abc def | abc def |
| abc,def | "abc,def" |
| abc"def | "abc""def" |
| abc\def | abc\def |

View File

@ -36,8 +36,9 @@
See: https://support.google.com/a/answer/7549103 See: https://support.google.com/a/answer/7549103
<QueryDeviceList> ::= "<QueryDevice>(,<QueryDevice>)*" <QueryDeviceList> ::= "<QueryDevice>(,<QueryDevice>)*"
<DeviceID> ::= devices/<String> <DeviceID> ::= devices/<String>
<DeviceIDList> ::= "<DeviceID>(,<DeviceID>)*"
<DeviceEntity> ::= <DeviceEntity> ::=
<DeviceIDList> | <DeviceIDList> | devicesn <String> |
(query:<QueryDevice>)|(query <QueryDevice>) (query:<QueryDevice>)|(query <QueryDevice>)
<DeviceType> ::= android|chrome_os|google_sync|linux|mac_os|windows <DeviceType> ::= android|chrome_os|google_sync|linux|mac_os|windows
<DeviceUserID> ::= devices/<String>/deviceUsers/<String> <DeviceUserID> ::= devices/<String>/deviceUsers/<String>

View File

@ -90,7 +90,7 @@
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])| [delimiter <Character>])|
@ -100,7 +100,7 @@
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])| [delimiter <Character>])|
@ -117,7 +117,7 @@
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])| [delimiter <Character>])|
@ -128,7 +128,7 @@
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)| (gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>)) (gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>]) [charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
@ -263,7 +263,7 @@ croscsvfile
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>] [delimiter <Character>]
@ -276,6 +276,7 @@ croscsvfile
* `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain ChromeOS deviceIds * `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain ChromeOS deviceIds
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file * `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used * `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `noescapechar <Boolean>` - Should `\` be ignored as an escape character; if not specified, the value of `csv_input_no_escape_char` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used * `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings * `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings * `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
@ -290,7 +291,7 @@ croscsvfile_sn
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>] [delimiter <Character>]
@ -303,6 +304,7 @@ croscsvfile_sn
* `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain ChromeOS serial numbers * `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain ChromeOS serial numbers
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file * `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used * `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `noescapechar <Boolean>` - Should `\` be ignored as an escape character; if not specified, the value of `csv_input_no_escape_char` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used * `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings * `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings * `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
@ -334,7 +336,7 @@ csvdatafile
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>] [delimiter <Character>]
@ -348,6 +350,7 @@ csvdatafile
* `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain ChromeOS deviceIds * `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain ChromeOS deviceIds
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file * `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used * `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `noescapechar <Boolean>` - Should `\` be ignored as an escape character; if not specified, the value of `csv_input_no_escape_char` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used * `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings * `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings * `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
@ -363,7 +366,7 @@ csvkmd
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)| (gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>)) (gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>]) [charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
@ -376,6 +379,7 @@ csvkmd
* `gdoc <UserGoogleDoc>` - A Google Doc containing rows with columns of the type of item specified * `gdoc <UserGoogleDoc>` - A Google Doc containing rows with columns of the type of item specified
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file * `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used * `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `noescapechar <Boolean>` - Should `\` be ignored as an escape character; if not specified, the value of `csv_input_no_escape_char` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used * `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings * `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings * `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings

View File

@ -63,7 +63,7 @@ A CSV file with one or more columns per row that contain Items.
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>] [delimiter <Character>]
@ -75,6 +75,7 @@ A CSV file with one or more columns per row that contain Items.
* `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain Items * `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain Items
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file * `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used * `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `noescapechar <Boolean>` - Should `\` be ignored as an escape character; if not specified, the value of `csv_input_no_escape_char` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used * `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings * `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings * `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
@ -90,7 +91,7 @@ A CSV file with a key column that contains an Item and optional subkey and data
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)| (gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>)) (gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>]) [charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
@ -102,6 +103,7 @@ A CSV file with a key column that contains an Item and optional subkey and data
* `gcscsv <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object containing rows with columns of items * `gcscsv <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object containing rows with columns of items
* `gcsdoc <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object containing rows with columns of items * `gcsdoc <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object containing rows with columns of items
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used * `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `noescapechar <Boolean>` - Should `\` be ignored as an escape character; if not specified, the value of `csv_input_no_escape_char` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used * `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings * `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings * `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings

View File

@ -127,7 +127,7 @@
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>][quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])| [delimiter <Character>])|
@ -148,7 +148,7 @@
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>][quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])| [delimiter <Character>])|
@ -161,7 +161,7 @@
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)| (gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>)) (gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>]) [charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>][quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
@ -360,7 +360,7 @@ csvfile
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>][quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>] [delimiter <Character>]
@ -373,7 +373,8 @@ csvfile
* `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain Users * `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns that contain Users
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file * `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used * `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used * `noescapechar <Boolean>` - Should `\` be ignored as an escape character; if not specified, the value of `csv_input_no_escape_char` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote character is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings * `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings * `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected * `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
@ -408,7 +409,7 @@ csvdatafile
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>][quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>] [delimiter <Character>]
@ -422,7 +423,8 @@ csvdatafile
* `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns contain the type of item specified * `gcsdoc(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns contain the type of item specified
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file * `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used * `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used * `noescapechar <Boolean>` - Should `\` be ignored as an escape character; if not specified, the value of `csv_input_no_escape_char` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote character is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings * `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings * `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected * `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
@ -439,7 +441,7 @@ csvkmd
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)| (gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>)) (gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>]) [charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>][quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
@ -454,7 +456,8 @@ csvkmd
* `gcsdoc <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object with columns of the type of item specified * `gcsdoc <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object with columns of the type of item specified
* `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file * `warnifnodata` - Issue message 'No CSV file data found' and exit with return code 60 if there is no data selected from the file
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used * `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used * `noescapechar <Boolean>` - Should `\` be ignored as an escape character; if not specified, the value of `csv_input_no_escape_char` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote character is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings * `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings * `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>])+` * `(keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>])+`

View File

@ -10,6 +10,29 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
See [Downloads](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads) for Windows or other options, including manual installation See [Downloads](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads) for Windows or other options, including manual installation
### 6.66.02
Updated device commmands to handle the following error caused by an invalid query.
```
ERROR: 400: invalidArgument - Request contains an invalid argument.
```
Added fields `deviceid` and `hostname` to `<DeviceFieldName>`.
### 6.66.01
Added the following variables to gam.cfg that allow control over whether `\` is used as an escape character
when reading/writing CSV files.
```
csv_input_no_escape_char - default value True
csv_output_no_escape_char - default value False
todrive_no_escape_char - default value True
```
When the value is True, `\` is ignored as an escape character; when the value is False,
`\\` on input is converted to `\`, `\` on output is converted to `\\`.
* See: https://github.com/taers232c/GAMADV-XTD3/wiki/CSV-Special-Characters
### 6.66.00 ### 6.66.00
Added support for `Focus Time` and `Out of Office` status events in user's primary calendars. Added support for `Focus Time` and `Out of Office` status events in user's primary calendars.

View File

@ -334,7 +334,7 @@ writes the credentials into the file oauth2.txt.
admin@server:/Users/admin/bin/gamadv-xtd3$ rm -f /Users/admin/GAMConfig/oauth2.txt admin@server:/Users/admin/bin/gamadv-xtd3$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam version admin@server:/Users/admin/bin/gamadv-xtd3$ ./gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAMADV-XTD3 6.66.00 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.66.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.10.8 64-bit final Python 3.10.8 64-bit final
MacOS High Sierra 10.13.6 x86_64 MacOS High Sierra 10.13.6 x86_64
@ -1002,7 +1002,7 @@ writes the credentials into the file oauth2.txt.
C:\GAMADV-XTD3>del C:\GAMConfig\oauth2.txt C:\GAMADV-XTD3>del C:\GAMConfig\oauth2.txt
C:\GAMADV-XTD3>gam version C:\GAMADV-XTD3>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAMADV-XTD3 6.66.00 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.66.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.0 64-bit final Python 3.12.0 64-bit final
Windows-10-10.0.17134 AMD64 Windows-10-10.0.17134 AMD64

View File

@ -112,7 +112,7 @@ You can redirect stdout and stderr to null and stderr can be redirected to stdou
``` ```
<Redirect> ::= <Redirect> ::=
redirect csv <FileName> [multiprocess] [append] [noheader] [charset <Charset>] redirect csv <FileName> [multiprocess] [append] [noheader] [charset <Charset>]
[columndelimiter <Character>] [quotechar <Character>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[timestampcolumn <String>] [timestampcolumn <String>]
[todrive <ToDriveAttribute>*] | [todrive <ToDriveAttribute>*] |
redirect stdout <FileName> [multiprocess] [append] | redirect stdout <FileName> [multiprocess] [append] |
@ -141,8 +141,11 @@ subsequent GAM commands specify `append noheader`.
The `charset <Charset>` subargument sets the character set of the CSV file; the default is the value of `charset` The `charset <Charset>` subargument sets the character set of the CSV file; the default is the value of `charset`
in `gam.cfg` which defaults to UTF-8. in `gam.cfg` which defaults to UTF-8.
The `columndelimiter <Character>` sets the intercolumn delimiter of the CSV file; the default value The `columndelimiter <Character>` subargument sets the intercolumn delimiter of the CSV file; the default value
is the value of csv_output_column_delimiter` in `gam.cfg` which defaults to comma. is the value of `csv_output_column_delimiter` in `gam.cfg` which defaults to comma.
The `noescapechar <Boolean>` subargument controls whether `\` is used as an escape character when writing the CSV file; the default value
is the value of `csv_output_no_escape_char` in `gam.cfg` which defaults to False.
The `quotechar <Character>` subargument sets the character used to quote fields in the CSV file The `quotechar <Character>` subargument sets the character used to quote fields in the CSV file
that contaim special charactere; the default value is the value of `csv_output_quote_char` in `gam.cfg` that contaim special charactere; the default value is the value of `csv_output_quote_char` in `gam.cfg`

View File

@ -167,7 +167,7 @@ gam create user <EmailAddress> <UserAttribute>*
gam update user <UserItem> <UserAttribute> gam update user <UserItem> <UserAttribute>
[updateprimaryemail <RegularExpression> <EmailReplacement>] [updateprimaryemail <RegularExpression> <EmailReplacement>]
[updateoufromgroup <FileName> [charset <CharSet>] [updateoufromgroup <FileName> [charset <CharSet>]
[columndelimiter <Character>] [quotechar <Character>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]] [fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]]
[clearschema <SchemaName>] [clearschema <SchemaName>.<FieldName>] [clearschema <SchemaName>] [clearschema <SchemaName>.<FieldName>]
[createifnotfound] [notify <EmailAddress>] [subject <String>] [createifnotfound] [notify <EmailAddress>] [subject <String>]

View File

@ -132,6 +132,9 @@ todrive_nobrowser
todrive_noemail todrive_noemail
Enable/disable sending an email when todrive is specified Enable/disable sending an email when todrive is specified
Default: True Default: True
todrive_no_escape_char
When writing a CSV file to Google Drive, should `\` be ignored as an escape character.
Default: True
todrive_parent todrive_parent
Parent folder for CSV files when todrive is specified; Parent folder for CSV files when todrive is specified;
can be id:<DriveFolderID> or <DriveFolderName> can be id:<DriveFolderID> or <DriveFolderName>
@ -180,6 +183,7 @@ direct the uploaded file to a particular user and location and add a timestamp t
(tdlocale <Locale>)| (tdlocale <Locale>)|
(tdnobrowser [<Boolean>])| (tdnobrowser [<Boolean>])|
(tdnoemail [<Boolean>])| (tdnoemail [<Boolean>])|
(tdnoescapechar [<Boolean>])|
(tdparent (id:<DriveFolderID>)|<DriveFolderName>)| (tdparent (id:<DriveFolderID>)|<DriveFolderName>)|
(tdretaintitle [<Boolean>])| (tdretaintitle [<Boolean>])|
(tdshare <EmailAddress> commenter|reader|writer)| (tdshare <EmailAddress> commenter|reader|writer)|
@ -233,6 +237,9 @@ If `tdfileid <DriveFileID>` is not specified, a new file is created.
* `tdnobrowser` - If False, a browser is opened to view the file uploaded to Google Drive; if not specified, the `todrive_nobrowser` value from gam.cfg is used. * `tdnobrowser` - If False, a browser is opened to view the file uploaded to Google Drive; if not specified, the `todrive_nobrowser` value from gam.cfg is used.
* `tdnoemail` - If False, an email is sent to `tduser` informing them of name and URL of the uploaded file; if not specified, the `todrive_noemail` value from gam.cfg is used. * `tdnoemail` - If False, an email is sent to `tduser` informing them of name and URL of the uploaded file; if not specified, the `todrive_noemail` value from gam.cfg is used.
## Escape character
* `tdnoescapechar <Boolean>` - Should `\` be ignored as an escape character; if not specified, the value of `todrive_no_escape_char` from `gam.cfg` will be used
## Local copy ## Local copy
* `tdlocalcopy` - Should a local copy of the CSV file be saved in addition to the file uploaded to Google Drive; if not specified, the `todrive_localcopy` value from gam.cfg is used. * `tdlocalcopy` - Should a local copy of the CSV file be saved in addition to the file uploaded to Google Drive; if not specified, the `todrive_localcopy` value from gam.cfg is used.
@ -265,7 +272,7 @@ If `tdfileid <DriveFileID>` is not specified, a new file is created.
You can specify `todrive` options in conjunction with `redirect csv`. You can specify `todrive` options in conjunction with `redirect csv`.
``` ```
redirect csv <FileName> [multiprocess] [append] [noheader] [charset <Charset>] redirect csv <FileName> [multiprocess] [append] [noheader] [charset <Charset>]
[columndelimiter <Character>] [quotechar <Character>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[todrive <ToDriveAttribute>*] [todrive <ToDriveAttribute>*]
``` ```
If you are doing `redirect csv <FileName> multiprocess`, it is more efficient to specify `todrive <ToDriveAttribute>*` as part of If you are doing `redirect csv <FileName> multiprocess`, it is more efficient to specify `todrive <ToDriveAttribute>*` as part of
@ -274,6 +281,8 @@ the redirect as verification of the `todrive` settings, which can invole several
`columndelimiter <Character>` and `quotechar <Character>` will not generally be used with `todrive` as `columndelimiter <Character>` and `quotechar <Character>` will not generally be used with `todrive` as
Google Sheets only recognizes `,` as the column delimiter and `"` as the quote character. Google Sheets only recognizes `,` as the column delimiter and `"` as the quote character.
`noescapechar true` will generally be used with `todrive` as Google Sheets does not recognize `\\` as an escaped `\`.
## Examples ## Examples
Generate a list of user IDs and names, title the file "User IDs and Names", upload it to the "GAM Reports" folder of usermgr@domain.com, add a timestamp to the title. Generate a list of user IDs and names, title the file "User IDs and Names", upload it to the "GAM Reports" folder of usermgr@domain.com, add a timestamp to the title.
``` ```

View File

@ -48,7 +48,7 @@
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)| (gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>)) (gcsdoc <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
<CSVFileSelector> ::= <CSVFileSelector> ::=
@ -57,7 +57,7 @@
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>] [delimiter <Character>]

View File

@ -78,7 +78,7 @@ gam <UserTypeEntity> print|show driveactivity [v2] [todrive <ToDriveAttributes>*
yesterday|today|thismonth|(previousmonths <Integer>)] yesterday|today|thismonth|(previousmonths <Integer>)]
[action|actions [not] <DriveActivityActionList>] [action|actions [not] <DriveActivityActionList>]
[consolidationstrategy legacy|none] [consolidationstrategy legacy|none]
[idmapfile <FileName>|(gsheet <UserGoogleSheet>) [charset <String>] [columndelimiter <Character>] [quotechar <Character>]] [idmapfile <FileName>|(gsheet <UserGoogleSheet>) [charset <String>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]]
[formatjson [quotechar <Character>]] [formatjson [quotechar <Character>]]
``` ```
By default, Drive Activity API v2 is used; the `v2` option is ignored. By default, Drive Activity API v2 is used; the `v2` option is ignored.

View File

@ -598,7 +598,7 @@ gam update user <UserItem> [ignorenullpassword] <UserAttribute>*
[verifynotinvitable|alwaysevict] [noactionifalias] [verifynotinvitable|alwaysevict] [noactionifalias]
[updateprimaryemail <RegularExpression> <EmailReplacement>] [updateprimaryemail <RegularExpression> <EmailReplacement>]
[updateoufromgroup <FileName> [charset <CharSet>] [updateoufromgroup <FileName> [charset <CharSet>]
[columndelimiter <Character>] [quotechar <Character>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]] [fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]]
[clearschema <SchemaName>] [clearschema <SchemaName>.<FieldName>] [clearschema <SchemaName>] [clearschema <SchemaName>.<FieldName>]
[createifnotfound] [notfoundpassword random|<Password>] [createifnotfound] [notfoundpassword random|<Password>]
@ -619,7 +619,7 @@ gam update users <UserTypeEntity> [ignorenullpassword] <UserAttribute>*
[verifynotinvitable|alwaysevict] [noactionifalias] [verifynotinvitable|alwaysevict] [noactionifalias]
[updateprimaryemail <RegularExpression> <EmailReplacement>] [updateprimaryemail <RegularExpression> <EmailReplacement>]
[updateoufromgroup <FileName> [charset <CharSet>] [updateoufromgroup <FileName> [charset <CharSet>]
[columndelimiter <Character>] [quotechar <Character>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]] [fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]]
[clearschema <SchemaName>] [clearschema <SchemaName>.<FieldName>] [clearschema <SchemaName>] [clearschema <SchemaName>.<FieldName>]
[createifnotfound] [notfoundpassword random|<Password>] [createifnotfound] [notfoundpassword random|<Password>]
@ -640,7 +640,7 @@ gam <UserTypeEntity> update users [ignorenullpassword] <UserAttribute>*
[verifynotinvitable|alwaysevict] [noactionifalias] [verifynotinvitable|alwaysevict] [noactionifalias]
[updateprimaryemail <RegularExpression> <EmailReplacement>] [updateprimaryemail <RegularExpression> <EmailReplacement>]
[updateoufromgroup <FileName> [charset <CharSet>] [updateoufromgroup <FileName> [charset <CharSet>]
[columndelimiter <Character>] [quotechar <Character>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]] [fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]]
[clearschema <SchemaName>] [clearschema <SchemaName>.<FieldName>] [clearschema <SchemaName>] [clearschema <SchemaName>.<FieldName>]
[createifnotfound] [notfoundpassword random|<Password>] [createifnotfound] [notfoundpassword random|<Password>]
@ -814,11 +814,12 @@ No update is performed if a user does not belong to any group in the CSV file or
``` ```
[updateoufromgroup <FileName> [charset <CharSet>] [updateoufromgroup <FileName> [charset <CharSet>]
[columndelimiter <Character>] [quotechar <Character>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]] [fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]]
``` ```
* `<FileName>` - A CSV file containing rows with columns of items * `<FileName>` - A CSV file containing rows with columns of items
* `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used * `columndelimiter <Character>` - Columns are separated by `<Character>`; if not specified, the value of `csv_input_column_delimiter` from `gam.cfg` will be used
* `noescapechar <Boolean>` - Should `\` be ignored as an escape character; if not specified, the value of `csv_input_no_escape_char` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used * `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings * `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `keyfield <FieldName>` - The column heading of the group column; the default is Group * `keyfield <FieldName>` - The column heading of the group column; the default is Group

View File

@ -4,7 +4,7 @@
Print the current version of Gam with details Print the current version of Gam with details
``` ```
gam version gam version
GAMADV-XTD3 6.66.00 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.66.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.0 64-bit final Python 3.12.0 64-bit final
MacOS Monterey 12.7 x86_64 MacOS Monterey 12.7 x86_64
@ -16,7 +16,7 @@ Time: 2023-06-02T21:10:00-07:00
Print the current version of Gam with details and time offset information Print the current version of Gam with details and time offset information
``` ```
gam version timeoffset gam version timeoffset
GAMADV-XTD3 6.66.00 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.66.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.0 64-bit final Python 3.12.0 64-bit final
MacOS Monterey 12.7 x86_64 MacOS Monterey 12.7 x86_64
@ -28,7 +28,7 @@ Your system time differs from www.googleapis.com by less than 1 second
Print the current version of Gam with extended details and SSL information Print the current version of Gam with extended details and SSL information
``` ```
gam version extended gam version extended
GAMADV-XTD3 6.66.00 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource GAMADV-XTD3 6.66.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.0 64-bit final Python 3.12.0 64-bit final
MacOS Monterey 12.7 x86_64 MacOS Monterey 12.7 x86_64
@ -65,7 +65,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gamadv-xtd3 Path: /Users/Admin/bin/gamadv-xtd3
Version Check: Version Check:
Current: 5.35.08 Current: 5.35.08
Latest: 6.66.00 Latest: 6.66.02
echo $? echo $?
1 1
``` ```
@ -73,7 +73,7 @@ echo $?
Print the current version number without details Print the current version number without details
``` ```
gam version simple gam version simple
6.66.00 6.66.02
``` ```
In Linux/MacOS you can do: In Linux/MacOS you can do:
``` ```
@ -83,7 +83,7 @@ echo $VER
Print the current version of Gam and address of this Wiki Print the current version of Gam and address of this Wiki
``` ```
gam help gam help
GAM 6.66.00 - https://github.com/taers232c/GAMADV-XTD3 GAM 6.66.02 - https://github.com/taers232c/GAMADV-XTD3
Ross Scroggs <ross.scroggs@gmail.com> Ross Scroggs <ross.scroggs@gmail.com>
Python 3.12.0 64-bit final Python 3.12.0 64-bit final
MacOS Monterey 12.7 x86_64 MacOS Monterey 12.7 x86_64

View File

@ -43,6 +43,7 @@ Command Processing
* [Command Line Parsing](Command-Line-Parsing) * [Command Line Parsing](Command-Line-Parsing)
* [Command Logging and Progress](Command-Logging-Progress) * [Command Logging and Progress](Command-Logging-Progress)
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage) * [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
* [CSV Special Characters](CSV-Special-Characters)
* [CSV Input Filtering](CSV-Input-Filtering) * [CSV Input Filtering](CSV-Input-Filtering)
* [CSV Output Filtering](CSV-Output-Filtering) * [CSV Output Filtering](CSV-Output-Filtering)
* [Meta Commands and File Redirection](Meta-Commands-and-File-Redirection) * [Meta Commands and File Redirection](Meta-Commands-and-File-Redirection)

View File

@ -148,6 +148,10 @@ csv_input_column_delimiter
All places where an input CSV file can be specified have an All places where an input CSV file can be specified have an
argument columndelimiter <String> that can override this value. argument columndelimiter <String> that can override this value.
Default: ',' Default: ','
csv_input_no_escape_char
When reading a CSV file, should `\` be ignored as an escape character.
Set this to False if the input file data was written using `\` as an escape character.
Default: True
csv_input_quote_char csv_input_quote_char
A one-character string used to quote fields containing special characters, A one-character string used to quote fields containing special characters,
such as the csv_input_column_delimiter or csv_input_quote_char, or newline characters. such as the csv_input_column_delimiter or csv_input_quote_char, or newline characters.
@ -209,11 +213,15 @@ csv_output_header_force
for inclusion in the CSV file written by a gam print command for inclusion in the CSV file written by a gam print command
Default: '' Default: ''
csv_output_line_terminator csv_output_line_terminator
Allowed values: cr, lf, crlf p Allowed values: cr, lf, crlf
Designates character(s) used to terminate the lines of a CSV file. Designates character(s) used to terminate the lines of a CSV file.
For Linux and Mac OS, this would typically be lf. For Linux and Mac OS, this would typically be lf.
For Windows, this would typically be crlf. For Windows, this would typically be crlf.
Default: lf Default: lf
csv_output_no_escape_char
When writing a CSV file, should `\` be ignored as an escape character.
Set this to True if the output file data is to be read by a non-Python program.
Default: False
csv_output_quote_char csv_output_quote_char
A one-character string used to quote fields containing special characters, A one-character string used to quote fields containing special characters,
such as the csv_output_column_delimiter or csv_output_quote_char such as the csv_output_column_delimiter or csv_output_quote_char
@ -527,6 +535,9 @@ todrive_nobrowser
todrive_noemail todrive_noemail
Enable/disable sending an email when todrive is specified Enable/disable sending an email when todrive is specified
Default: True Default: True
todrive_no_escape_char
When writing a CSV file to Google Drive, should `\` be ignored as an escape character.
Default: True
todrive_parent todrive_parent
Parent folder for CSV files when todrive is specified; Parent folder for CSV files when todrive is specified;
can be id:<DriveFolderID> or <DriveFolderName> can be id:<DriveFolderID> or <DriveFolderName>
@ -605,6 +616,7 @@ Section: DEFAULT
config_dir = /Users/admin/.gam config_dir = /Users/admin/.gam
contact_max_results = 100 contact_max_results = 100
csv_input_column_delimiter = , csv_input_column_delimiter = ,
csv_input_no_escape_char = true
csv_input_quote_char = '"' csv_input_quote_char = '"'
csv_input_row_drop_filter = '' csv_input_row_drop_filter = ''
csv_input_row_drop_filter = '' csv_input_row_drop_filter = ''
@ -619,6 +631,7 @@ Section: DEFAULT
csv_output_header_filter = '' csv_output_header_filter = ''
csv_output_header_force = '' csv_output_header_force = ''
csv_output_line_terminator = lf csv_output_line_terminator = lf
csv_output_no_escape_char = false
csv_output_quote_char = '"' csv_output_quote_char = '"'
csv_output_row_drop_filter = '' csv_output_row_drop_filter = ''
csv_output_row_drop_filter_mode = anymatch csv_output_row_drop_filter_mode = anymatch
@ -689,6 +702,7 @@ Section: DEFAULT
todrive_locale = '' todrive_locale = ''
todrive_nobrowser = false todrive_nobrowser = false
todrive_noemail = true todrive_noemail = true
todrive_no_escape_char = true
todrive_parent = root todrive_parent = root
todrive_sheet_timeformat = '' todrive_sheet_timeformat = ''
todrive_sheet_timestamp = false todrive_sheet_timestamp = false
@ -797,6 +811,7 @@ clock_skew_in_seconds = 10
config_dir = /Users/admin/.gam config_dir = /Users/admin/.gam
contact_max_results = 100 contact_max_results = 100
csv_input_column_delimiter = , csv_input_column_delimiter = ,
csv_input_no_escape_char = true
csv_input_quote_char = '"' csv_input_quote_char = '"'
csv_input_row_drop_filter = '' csv_input_row_drop_filter = ''
csv_input_row_filter = '' csv_input_row_filter = ''
@ -807,6 +822,7 @@ csv_output_header_drop_filter = ''
csv_output_header_filter = '' csv_output_header_filter = ''
csv_output_header_force = '' csv_output_header_force = ''
csv_output_line_terminator = lf csv_output_line_terminator = lf
csv_output_no_escape_char = false
csv_output_quote_char = '"' csv_output_quote_char = '"'
csv_output_row_drop_filter = csv_output_row_drop_filter =
csv_output_row_filter = '' csv_output_row_filter = ''
@ -873,6 +889,7 @@ todrive_localcopy = false
todrive_locale = '' todrive_locale = ''
todrive_nobrowser = false todrive_nobrowser = false
todrive_noemail = true todrive_noemail = true
todrive_no_escape_char = true
todrive_parent = root todrive_parent = root
todrive_sheet_timeformat = '' todrive_sheet_timeformat = ''
todrive_sheet_timestamp = false todrive_sheet_timestamp = false

View File

@ -609,6 +609,7 @@ If an item contains spaces, it should be surrounded by ".
(tdlocale <Locale>)| (tdlocale <Locale>)|
(tdnobrowser [<Boolean>])| (tdnobrowser [<Boolean>])|
(tdnoemail [<Boolean>])| (tdnoemail [<Boolean>])|
(tdnoescapechar [<Boolean>])|
(tdparent (id:<DriveFolderID>)|<DriveFolderName>)| (tdparent (id:<DriveFolderID>)|<DriveFolderName>)|
(tdretaintitle [<Boolean>])| (tdretaintitle [<Boolean>])|
(tdshare <EmailAddress> commenter|reader|writer)| (tdshare <EmailAddress> commenter|reader|writer)|
@ -788,7 +789,7 @@ Specify a collection of ChromeOS devices by directly specifying them or by speci
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])| [delimiter <Character>])|
@ -798,7 +799,7 @@ Specify a collection of ChromeOS devices by directly specifying them or by speci
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])| [delimiter <Character>])|
@ -815,7 +816,7 @@ Specify a collection of ChromeOS devices by directly specifying them or by speci
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])| [delimiter <Character>])|
@ -826,7 +827,7 @@ Specify a collection of ChromeOS devices by directly specifying them or by speci
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)| (gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>)) (gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>]) [charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
@ -874,7 +875,7 @@ Specify a collection of Users by directly specifying them or by specifiying item
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])| [delimiter <Character>])|
@ -895,7 +896,7 @@ Specify a collection of Users by directly specifying them or by specifiying item
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>])| [delimiter <Character>])|
@ -908,7 +909,7 @@ Specify a collection of Users by directly specifying them or by specifiying item
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)| (gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>)) (gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>]) [charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
@ -925,7 +926,7 @@ Specify a collection of items by directly specifying them; the item type is dete
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)| (gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>)) (gcsdoc <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
<FileSelector> ::= <FileSelector> ::=
@ -941,7 +942,7 @@ Specify a collection of items by directly specifying them; the item type is dete
(gdoc(:<FieldName>)+ <UserGoogleDoc>)| (gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)| (gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>)) (gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [quotechar <Character>] [warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)] [endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
[delimiter <Character>] [delimiter <Character>]
@ -956,7 +957,7 @@ Specify a collection of items by directly specifying them; the item type is dete
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)| (gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>)) (gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>]) [charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] keyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>] subkeyfield <FieldName> [keypattern <RegularExpression>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RegularExpression>)* (matchfield|skipfield <FieldName> <RegularExpression>)*
@ -1237,7 +1238,7 @@ If the pattern {{Section}} appears in <FileName>, it will be replaced with the n
For redirect csv, the optional arguments must appear in the order shown. For redirect csv, the optional arguments must appear in the order shown.
<Redirect> ::= <Redirect> ::=
redirect csv <FileName> [multiprocess] [append] [noheader] [charset <Charset>] redirect csv <FileName> [multiprocess] [append] [noheader] [charset <Charset>]
[columndelimiter <Character>] [quotechar <Character>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[timestampcolumn <String>] [timestampcolumn <String>]
[todrive <ToDriveAttribute>*] | [todrive <ToDriveAttribute>*] |
redirect stdout <FileName> [multiprocess] [append] | redirect stdout <FileName> [multiprocess] [append] |
@ -1284,13 +1285,13 @@ gam tbatch <BatchContent> [showcmds [<Boolean>]]
[charset <Charset>] [delimiter <Character>]) [charset <Charset>] [delimiter <Character>])
gam csv <CSVLoopContent> [warnifnodata] gam csv <CSVLoopContent> [warnifnodata]
[columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>]
(matchfield|skipfield <FieldName> <RegularExpression>)* [showcmds [<Boolean>]] (matchfield|skipfield <FieldName> <RegularExpression>)* [showcmds [<Boolean>]]
[maxrows <Integer>] [maxrows <Integer>]
gam <GAMArgumentList> gam <GAMArgumentList>
gam loop <CSVLoopContent> [warnifnodata] gam loop <CSVLoopContent> [warnifnodata]
[columndelimiter <Character>] [quotechar <Character>] [fields <FieldNameList>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>]
(matchfield|skipfield <FieldName> <RegularExpression>)* [showcmds [<Boolean>]] (matchfield|skipfield <FieldName> <RegularExpression>)* [showcmds [<Boolean>]]
[maxrows <Integer>] [maxrows <Integer>]
gam <GAMArgumentList> gam <GAMArgumentList>
@ -3766,9 +3767,12 @@ gam show cigroup-members
# Cloud Identity Devices # Cloud Identity Devices
<DeviceID> ::= devices/<String> <DeviceID> ::= devices/<String>
<DeviceUserID> ::= devices/<String>/deviceUsers/<String> <DeviceIDList> ::= "<DeviceID>(,<DeviceID>)*"
<DeviceEntity> ::=
<DeviceIDList> | devicesn <String> |
(query:<QueryDevice>)|(query <QueryDevice>)
<DeviceType> ::= android|chrome_os|google_sync|ios|linux|mac_os|windows <DeviceType> ::= android|chrome_os|google_sync|ios|linux|mac_os|windows
<DeviceUserID> ::= devices/<String>/deviceUsers/<String>
<DeviceFieldName> ::= <DeviceFieldName> ::=
androidspecificattributes| androidspecificattributes|
assettag| assettag|
@ -3778,11 +3782,13 @@ gam show cigroup-members
buildnumber| buildnumber|
compromisedstate| compromisedstate|
createtime| createtime|
deviceid|
devicetype| devicetype|
enableddeveloperoptions| enableddeveloperoptions|
enabledusbdebugging| enabledusbdebugging|
endpointverificationspecificattributes| endpointverificationspecificattributes|
encryptionstate| encryptionstate|
hostname|
imei| imei|
kernelversion| kernelversion|
lastsynctime| lastsynctime|
@ -5203,7 +5209,7 @@ gam update user <UserItem> [ignorenullpassword] <UserAttribute>*
[verifynotinvitable|alwaysevict] [noactionifalias] [verifynotinvitable|alwaysevict] [noactionifalias]
[updateprimaryemail <RegularExpression> <EmailReplacement>] [updateprimaryemail <RegularExpression> <EmailReplacement>]
[updateoufromgroup <FileName> [charset <CharSet>] [updateoufromgroup <FileName> [charset <CharSet>]
[columndelimiter <Character>] [quotechar <Character>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]] [fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]]
[immutableous <OrgUnitEntity>]| [immutableous <OrgUnitEntity>]|
[clearschema <SchemaName>] [clearschema <SchemaName>.<FieldName>] [clearschema <SchemaName>] [clearschema <SchemaName>.<FieldName>]
@ -5239,7 +5245,7 @@ gam update users <UserTypeEntity> [ignorenullpassword] <UserAttribute>*
[verifynotinvitable] [noactionifalias] [verifynotinvitable] [noactionifalias]
[updateprimaryemail <RegularExpression> <EmailReplacement>] [updateprimaryemail <RegularExpression> <EmailReplacement>]
[updateoufromgroup <FileName> [charset <CharSet>] [updateoufromgroup <FileName> [charset <CharSet>]
[columndelimiter <Character>] [quotechar <Character>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]] [fields <FieldNameList>] [keyfield <FieldName>] [datafield <FieldName>]]
[clearschema <SchemaName>] [clearschema <SchemaName>.<FieldName>] [clearschema <SchemaName>] [clearschema <SchemaName>.<FieldName>]
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>] [createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]

View File

@ -2,6 +2,29 @@
Merged GAM-Team version Merged GAM-Team version
6.66.02
Updated device commmands to handle the following error caused by an invalid query.
```
ERROR: 400: invalidArgument - Request contains an invalid argument.
```
Added fields `deviceid` and `hostname` to `<DeviceFieldName>`.
6.66.01
Added the following variables to gam.cfg that allow control over whether `\` is used as an escape character
when reading/writing CSV files.
```
csv_input_no_escape_char - default value True
csv_output_no_escape_char - default value False
todrive_no_escape_char - default value True
```
When the value is True, `\` is ignored as an escape character; when the value is False,
`\\` on input is converted to `\`, `\` on output is converted to `\\`.
* See: https://github.com/taers232c/GAMADV-XTD3/wiki/CSV-Special-Characters
6.66.00 6.66.00
Added support for `Focus Time` and `Out of Office` status events in user's primary calendars. Added support for `Focus Time` and `Out of Office` status events in user's primary calendars.

View File

@ -3173,6 +3173,10 @@ def openCSVFileReader(filename, fieldnames=None):
columnDelimiter = getCharacter() columnDelimiter = getCharacter()
else: else:
columnDelimiter = GC.Values[GC.CSV_INPUT_COLUMN_DELIMITER] columnDelimiter = GC.Values[GC.CSV_INPUT_COLUMN_DELIMITER]
if checkArgumentPresent('noescapechar'):
noEscapeChar = getBoolean()
else:
noEscapeChar = GC.Values[GC.CSV_INPUT_NO_ESCAPE_CHAR]
if checkArgumentPresent('quotechar'): if checkArgumentPresent('quotechar'):
quotechar = getCharacter() quotechar = getCharacter()
else: else:
@ -3180,7 +3184,10 @@ def openCSVFileReader(filename, fieldnames=None):
if not checkArgumentPresent('endcsv') and checkArgumentPresent('fields'): if not checkArgumentPresent('endcsv') and checkArgumentPresent('fields'):
fieldnames = shlexSplitList(getString(Cmd.OB_FIELD_NAME_LIST)) fieldnames = shlexSplitList(getString(Cmd.OB_FIELD_NAME_LIST))
try: try:
csvFile = csv.DictReader(f, fieldnames=fieldnames, delimiter=columnDelimiter, quotechar=quotechar) csvFile = csv.DictReader(f, fieldnames=fieldnames,
delimiter=columnDelimiter,
escapechar='\\' if not noEscapeChar else None,
quotechar=quotechar)
return (f, csvFile, csvFile.fieldnames if csvFile.fieldnames is not None else []) return (f, csvFile, csvFile.fieldnames if csvFile.fieldnames is not None else [])
except (csv.Error, UnicodeDecodeError, UnicodeError) as e: except (csv.Error, UnicodeDecodeError, UnicodeError) as e:
systemErrorExit(FILE_ERROR_RC, e) systemErrorExit(FILE_ERROR_RC, e)
@ -3343,6 +3350,8 @@ def SetGlobalVariables():
value = codecs.escape_decode(bytes(_stripStringQuotes(GM.Globals[GM.PARSER].get(sectionName, itemName)), UTF8))[0].decode(UTF8) value = codecs.escape_decode(bytes(_stripStringQuotes(GM.Globals[GM.PARSER].get(sectionName, itemName)), UTF8))[0].decode(UTF8)
if not value and (itemName == 'csv_output_field_delimiter'): if not value and (itemName == 'csv_output_field_delimiter'):
return ' ' return ' '
if not value and (itemName in {'csv_input_escape_char', 'csv_output_escape_char'}):
return None
if len(value) == 1: if len(value) == 1:
return value return value
_printValueError(sectionName, itemName, f'"{value}"', f'{Msg.EXPECTED}: {integerLimits(1, 1, Msg.STRING_LENGTH)}') _printValueError(sectionName, itemName, f'"{value}"', f'{Msg.EXPECTED}: {integerLimits(1, 1, Msg.STRING_LENGTH)}')
@ -4033,7 +4042,7 @@ def SetGlobalVariables():
if checkArgumentPresent(Cmd.MULTIPROCESSEXIT_CMD): if checkArgumentPresent(Cmd.MULTIPROCESSEXIT_CMD):
_setMultiprocessExit() _setMultiprocessExit()
# redirect csv <FileName> [multiprocess] [append] [noheader] [charset <CharSet>] # redirect csv <FileName> [multiprocess] [append] [noheader] [charset <CharSet>]
# [columndelimiter <Character>] [quotechar <Character>]] # [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]]
# [timestampcolumn <String>] # [timestampcolumn <String>]
# [todrive <ToDriveAttribute>*] # [todrive <ToDriveAttribute>*]
# redirect stdout <FileName> [multiprocess] [append] # redirect stdout <FileName> [multiprocess] [append]
@ -4053,6 +4062,8 @@ def SetGlobalVariables():
GM.Globals[GM.CSV_OUTPUT_COLUMN_DELIMITER] = GC.Values[GC.CSV_OUTPUT_COLUMN_DELIMITER] = getCharacter() GM.Globals[GM.CSV_OUTPUT_COLUMN_DELIMITER] = GC.Values[GC.CSV_OUTPUT_COLUMN_DELIMITER] = getCharacter()
if checkArgumentPresent('quotechar'): if checkArgumentPresent('quotechar'):
GM.Globals[GM.CSV_OUTPUT_QUOTE_CHAR] = GC.Values[GC.CSV_OUTPUT_QUOTE_CHAR] = getCharacter() GM.Globals[GM.CSV_OUTPUT_QUOTE_CHAR] = GC.Values[GC.CSV_OUTPUT_QUOTE_CHAR] = getCharacter()
if checkArgumentPresent('noescapechar'):
GM.Globals[GM.CSV_OUTPUT_NO_ESCAPE_CHAR] = GC.Values[GC.CSV_OUTPUT_NO_ESCAPE_CHAR] = getBoolean()
if checkArgumentPresent('timestampcolumn'): if checkArgumentPresent('timestampcolumn'):
GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN] = GC.Values[GC.CSV_OUTPUT_TIMESTAMP_COLUMN] = getString(Cmd.OB_STRING, minLen=0) GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN] = GC.Values[GC.CSV_OUTPUT_TIMESTAMP_COLUMN] = getString(Cmd.OB_STRING, minLen=0)
_setCSVFile(filename, mode, encoding, writeHeader, multi) _setCSVFile(filename, mode, encoding, writeHeader, multi)
@ -7601,7 +7612,9 @@ class CSVPrintFile():
self.SetColumnDelimiter(GM.Globals[GM.CSV_OUTPUT_COLUMN_DELIMITER]) self.SetColumnDelimiter(GM.Globals[GM.CSV_OUTPUT_COLUMN_DELIMITER])
if GM.Globals.get(GM.CSV_OUTPUT_QUOTE_CHAR) is None: if GM.Globals.get(GM.CSV_OUTPUT_QUOTE_CHAR) is None:
GM.Globals[GM.CSV_OUTPUT_QUOTE_CHAR] = GC.Values.get(GC.CSV_OUTPUT_QUOTE_CHAR, '"') GM.Globals[GM.CSV_OUTPUT_QUOTE_CHAR] = GC.Values.get(GC.CSV_OUTPUT_QUOTE_CHAR, '"')
self.SetEscapeChar('\\') if GM.Globals.get(GM.CSV_OUTPUT_NO_ESCAPE_CHAR) is None:
GM.Globals[GM.CSV_OUTPUT_NO_ESCAPE_CHAR] = GC.Values.get(GC.CSV_OUTPUT_NO_ESCAPE_CHAR, False)
self.SetNoEscapeChar(GM.Globals[GM.CSV_OUTPUT_NO_ESCAPE_CHAR])
self.SetQuoteChar(GM.Globals[GM.CSV_OUTPUT_QUOTE_CHAR]) self.SetQuoteChar(GM.Globals[GM.CSV_OUTPUT_QUOTE_CHAR])
if GM.Globals.get(GM.CSV_OUTPUT_TIMESTAMP_COLUMN) is None: if GM.Globals.get(GM.CSV_OUTPUT_TIMESTAMP_COLUMN) is None:
GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN] = GC.Values.get(GC.CSV_OUTPUT_TIMESTAMP_COLUMN, '') GM.Globals[GM.CSV_OUTPUT_TIMESTAMP_COLUMN] = GC.Values.get(GC.CSV_OUTPUT_TIMESTAMP_COLUMN, '')
@ -7812,6 +7825,7 @@ class CSVPrintFile():
'backupSheetEntity': None, 'copySheetEntity': None, 'backupSheetEntity': None, 'copySheetEntity': None,
'locale': GC.Values[GC.TODRIVE_LOCALE], 'timeZone': GC.Values[GC.TODRIVE_TIMEZONE], 'locale': GC.Values[GC.TODRIVE_LOCALE], 'timeZone': GC.Values[GC.TODRIVE_TIMEZONE],
'timestamp': GC.Values[GC.TODRIVE_TIMESTAMP], 'timeformat': GC.Values[GC.TODRIVE_TIMEFORMAT], 'timestamp': GC.Values[GC.TODRIVE_TIMESTAMP], 'timeformat': GC.Values[GC.TODRIVE_TIMEFORMAT],
'noescapechar': GC.Values[GC.TODRIVE_NO_ESCAPE_CHAR],
'daysoffset': None, 'hoursoffset': None, 'daysoffset': None, 'hoursoffset': None,
'sheettimestamp': GC.Values[GC.TODRIVE_SHEET_TIMESTAMP], 'sheettimeformat': GC.Values[GC.TODRIVE_SHEET_TIMEFORMAT], 'sheettimestamp': GC.Values[GC.TODRIVE_SHEET_TIMESTAMP], 'sheettimeformat': GC.Values[GC.TODRIVE_SHEET_TIMEFORMAT],
'sheetdaysoffset': None, 'sheethoursoffset': None, 'sheetdaysoffset': None, 'sheethoursoffset': None,
@ -7888,6 +7902,8 @@ class CSVPrintFile():
self.todrive['nobrowser'] = getBoolean() self.todrive['nobrowser'] = getBoolean()
elif myarg == 'tdnoemail': elif myarg == 'tdnoemail':
self.todrive['noemail'] = getBoolean() self.todrive['noemail'] = getBoolean()
elif myarg == 'tdnoescapechar':
self.todrive['noescapechar'] = getBoolean()
elif myarg == 'tdshare': elif myarg == 'tdshare':
self.todrive['share']['emailAddress'] = normalizeEmailAddressOrUID(getString(Cmd.OB_EMAIL_ADDRESS)) self.todrive['share']['emailAddress'] = normalizeEmailAddressOrUID(getString(Cmd.OB_EMAIL_ADDRESS))
self.todrive['share']['type'] = 'user' self.todrive['share']['type'] = 'user'
@ -8119,8 +8135,8 @@ class CSVPrintFile():
def SetColumnDelimiter(self, columnDelimiter): def SetColumnDelimiter(self, columnDelimiter):
self.columnDelimiter = columnDelimiter self.columnDelimiter = columnDelimiter
def SetEscapeChar(self, escapeChar): def SetNoEscapeChar(self, noEscapeChar):
self.escapeChar = escapeChar self.noEscapeChar = noEscapeChar
def SetQuoteChar(self, quoteChar): def SetQuoteChar(self, quoteChar):
self.quoteChar = quoteChar self.quoteChar = quoteChar
@ -8318,11 +8334,11 @@ class CSVPrintFile():
stderrErrorMsg(e) stderrErrorMsg(e)
return False return False
def setDialect(lineterminator): def setDialect(lineterminator, noEscapeChar):
writerDialect = { writerDialect = {
'delimiter': self.columnDelimiter, 'delimiter': self.columnDelimiter,
'doublequote': True, 'doublequote': True,
'escapechar': self.escapeChar, 'escapechar': '\\' if not noEscapeChar else None,
'lineterminator': lineterminator, 'lineterminator': lineterminator,
'quotechar': self.quoteChar, 'quotechar': self.quoteChar,
'quoting': csv.QUOTE_MINIMAL, 'quoting': csv.QUOTE_MINIMAL,
@ -8332,7 +8348,7 @@ class CSVPrintFile():
def writeCSVToStdout(): def writeCSVToStdout():
csvFile = StringIOobject() csvFile = StringIOobject()
writerDialect = setDialect('\n') writerDialect = setDialect('\n', self.noEscapeChar)
writer = csv.DictWriter(csvFile, titlesList, extrasaction=extrasaction, **writerDialect) writer = csv.DictWriter(csvFile, titlesList, extrasaction=extrasaction, **writerDialect)
if writeCSVData(writer): if writeCSVData(writer):
try: try:
@ -8347,7 +8363,7 @@ class CSVPrintFile():
encoding=GM.Globals[GM.CSVFILE][GM.REDIRECT_ENCODING], errors='backslashreplace', encoding=GM.Globals[GM.CSVFILE][GM.REDIRECT_ENCODING], errors='backslashreplace',
continueOnError=True) continueOnError=True)
if csvFile: if csvFile:
writerDialect = setDialect(str(GC.Values[GC.CSV_OUTPUT_LINE_TERMINATOR])) writerDialect = setDialect(str(GC.Values[GC.CSV_OUTPUT_LINE_TERMINATOR]), self.noEscapeChar)
writer = csv.DictWriter(csvFile, titlesList, extrasaction=extrasaction, **writerDialect) writer = csv.DictWriter(csvFile, titlesList, extrasaction=extrasaction, **writerDialect)
writeCSVData(writer) writeCSVData(writer)
closeFile(csvFile) closeFile(csvFile)
@ -8363,7 +8379,7 @@ class CSVPrintFile():
csvFile = TemporaryFile(mode='w+', encoding=UTF8) csvFile = TemporaryFile(mode='w+', encoding=UTF8)
else: else:
csvFile = StringIOobject() csvFile = StringIOobject()
writerDialect = setDialect('\n') writerDialect = setDialect('\n', self.todrive['noescapechar'])
writer = csv.DictWriter(csvFile, titlesList, extrasaction=extrasaction, **writerDialect) writer = csv.DictWriter(csvFile, titlesList, extrasaction=extrasaction, **writerDialect)
if writeCSVData(writer): if writeCSVData(writer):
if ((self.todrive['title'] is None) or if ((self.todrive['title'] is None) or
@ -8639,7 +8655,7 @@ class CSVPrintFile():
GM.Globals[GM.CSVFILE][GM.REDIRECT_QUEUE].put((GM.REDIRECT_QUEUE_CSVPF, GM.Globals[GM.CSVFILE][GM.REDIRECT_QUEUE].put((GM.REDIRECT_QUEUE_CSVPF,
(self.titlesList, self.sortTitlesList, self.indexedTitles, (self.titlesList, self.sortTitlesList, self.indexedTitles,
self.formatJSON, self.JSONtitlesList, self.formatJSON, self.JSONtitlesList,
self.columnDelimiter, self.quoteChar, self.columnDelimiter, self.noEscapeChar, self.quoteChar,
self.timestampColumn, self.timestampColumn,
self.mapDrive3Titles, self.mapDrive3Titles,
self.fixPaths, self.fixPaths,
@ -9244,6 +9260,7 @@ def CSVFileQueueHandler(mpQueue, mpQueueStdout, mpQueueStderr, csvPF, datetimeNo
Cmd = glclargs.GamCLArgs() Cmd = glclargs.GamCLArgs()
else: else:
csvPF.SetColumnDelimiter(GC.Values[GC.CSV_OUTPUT_COLUMN_DELIMITER]) csvPF.SetColumnDelimiter(GC.Values[GC.CSV_OUTPUT_COLUMN_DELIMITER])
csvPF.SetNoEscapeChar(GC.Values[GC.CSV_OUTPUT_NO_ESCAPE_CHAR])
csvPF.SetQuoteChar(GC.Values[GC.CSV_OUTPUT_QUOTE_CHAR]) csvPF.SetQuoteChar(GC.Values[GC.CSV_OUTPUT_QUOTE_CHAR])
csvPF.SetTimestampColumn(GC.Values[GC.CSV_OUTPUT_TIMESTAMP_COLUMN]) csvPF.SetTimestampColumn(GC.Values[GC.CSV_OUTPUT_TIMESTAMP_COLUMN])
csvPF.SetHeaderFilter(GC.Values[GC.CSV_OUTPUT_HEADER_FILTER]) csvPF.SetHeaderFilter(GC.Values[GC.CSV_OUTPUT_HEADER_FILTER])
@ -9265,13 +9282,14 @@ def CSVFileQueueHandler(mpQueue, mpQueueStdout, mpQueueStderr, csvPF, datetimeNo
csvPF.SetFormatJSON(dataItem[3]) csvPF.SetFormatJSON(dataItem[3])
csvPF.AddJSONTitles(dataItem[4]) csvPF.AddJSONTitles(dataItem[4])
csvPF.SetColumnDelimiter(dataItem[5]) csvPF.SetColumnDelimiter(dataItem[5])
csvPF.SetQuoteChar(dataItem[6]) csvPF.SetNoEscapeChar(dataItem[6])
csvPF.SetTimestampColumn(dataItem[7]) csvPF.SetQuoteChar(dataItem[7])
csvPF.SetMapDrive3Titles(dataItem[8]) csvPF.SetTimestampColumn(dataItem[8])
csvPF.SetFixPaths(dataItem[9]) csvPF.SetMapDrive3Titles(dataItem[9])
csvPF.SetNodataFields(dataItem[10], dataItem[11], dataItem[12], dataItem[13], dataItem[14]) csvPF.SetFixPaths(dataItem[10])
csvPF.SetShowPermissionsLast(dataItem[15]) csvPF.SetNodataFields(dataItem[11], dataItem[12], dataItem[13], dataItem[14], dataItem[15])
csvPF.SetZeroBlankMimeTypeCounts(dataItem[16]) csvPF.SetShowPermissionsLast(dataItem[16])
csvPF.SetZeroBlankMimeTypeCounts(dataItem[17])
elif dataType == GM.REDIRECT_QUEUE_DATA: elif dataType == GM.REDIRECT_QUEUE_DATA:
csvPF.rows.extend(dataItem) csvPF.rows.extend(dataItem)
elif dataType == GM.REDIRECT_QUEUE_ARGS: elif dataType == GM.REDIRECT_QUEUE_ARGS:
@ -9284,6 +9302,7 @@ def CSVFileQueueHandler(mpQueue, mpQueueStdout, mpQueueStderr, csvPF, datetimeNo
elif dataType == GM.REDIRECT_QUEUE_VALUES: elif dataType == GM.REDIRECT_QUEUE_VALUES:
GC.Values = dataItem GC.Values = dataItem
csvPF.SetColumnDelimiter(GC.Values[GC.CSV_OUTPUT_COLUMN_DELIMITER]) csvPF.SetColumnDelimiter(GC.Values[GC.CSV_OUTPUT_COLUMN_DELIMITER])
csvPF.SetNoEscapeChar(GC.Values[GC.CSV_OUTPUT_NO_ESCAPE_CHAR])
csvPF.SetQuoteChar(GC.Values[GC.CSV_OUTPUT_QUOTE_CHAR]) csvPF.SetQuoteChar(GC.Values[GC.CSV_OUTPUT_QUOTE_CHAR])
csvPF.SetTimestampColumn(GC.Values[GC.CSV_OUTPUT_TIMESTAMP_COLUMN]) csvPF.SetTimestampColumn(GC.Values[GC.CSV_OUTPUT_TIMESTAMP_COLUMN])
csvPF.SetHeaderFilter(GC.Values[GC.CSV_OUTPUT_HEADER_FILTER]) csvPF.SetHeaderFilter(GC.Values[GC.CSV_OUTPUT_HEADER_FILTER])
@ -9427,7 +9446,7 @@ def ProcessGAMCommandMulti(pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout,
debugLevel, todrive, printAguDomains, debugLevel, todrive, printAguDomains,
printCrosOUs, printCrosOUsAndChildren, printCrosOUs, printCrosOUsAndChildren,
output_dateformat, output_timeformat, output_dateformat, output_timeformat,
csvColumnDelimiter, csvQuoteChar, csvColumnDelimiter, csvNoEscapeChar, csvQuoteChar,
csvTimestampColumn, csvTimestampColumn,
csvHeaderFilter, csvHeaderDropFilter, csvHeaderFilter, csvHeaderDropFilter,
csvHeaderForce, csvHeaderForce,
@ -9449,6 +9468,7 @@ def ProcessGAMCommandMulti(pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout,
GM.Globals[GM.CSV_SUBKEY_FIELD] = None GM.Globals[GM.CSV_SUBKEY_FIELD] = None
GM.Globals[GM.CSV_DATA_FIELD] = None GM.Globals[GM.CSV_DATA_FIELD] = None
GM.Globals[GM.CSV_OUTPUT_COLUMN_DELIMITER] = csvColumnDelimiter GM.Globals[GM.CSV_OUTPUT_COLUMN_DELIMITER] = csvColumnDelimiter
GM.Globals[GM.CSV_OUTPUT_NO_ESCAPE_CHAR] = csvNoEscapeChar
GM.Globals[GM.CSV_OUTPUT_HEADER_DROP_FILTER] = csvHeaderDropFilter[:] GM.Globals[GM.CSV_OUTPUT_HEADER_DROP_FILTER] = csvHeaderDropFilter[:]
GM.Globals[GM.CSV_OUTPUT_HEADER_FILTER] = csvHeaderFilter[:] GM.Globals[GM.CSV_OUTPUT_HEADER_FILTER] = csvHeaderFilter[:]
GM.Globals[GM.CSV_OUTPUT_HEADER_FORCE] = csvHeaderForce[:] GM.Globals[GM.CSV_OUTPUT_HEADER_FORCE] = csvHeaderForce[:]
@ -9658,6 +9678,7 @@ def MultiprocessGAMCommands(items, showCmds):
GC.Values[GC.PRINT_CROS_OUS], GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN], GC.Values[GC.PRINT_CROS_OUS], GC.Values[GC.PRINT_CROS_OUS_AND_CHILDREN],
GC.Values[GC.OUTPUT_DATEFORMAT], GC.Values[GC.OUTPUT_TIMEFORMAT], GC.Values[GC.OUTPUT_DATEFORMAT], GC.Values[GC.OUTPUT_TIMEFORMAT],
GC.Values[GC.CSV_OUTPUT_COLUMN_DELIMITER], GC.Values[GC.CSV_OUTPUT_COLUMN_DELIMITER],
GC.Values[GC.CSV_OUTPUT_NO_ESCAPE_CHAR],
GC.Values[GC.CSV_OUTPUT_QUOTE_CHAR], GC.Values[GC.CSV_OUTPUT_QUOTE_CHAR],
GC.Values[GC.CSV_OUTPUT_TIMESTAMP_COLUMN], GC.Values[GC.CSV_OUTPUT_TIMESTAMP_COLUMN],
GC.Values[GC.CSV_OUTPUT_HEADER_FILTER], GC.Values[GC.CSV_OUTPUT_HEADER_FILTER],
@ -22261,7 +22282,7 @@ def printShowUserPeopleContactGroups(users):
entityTypeName = Ent.Singular(entityType) entityTypeName = Ent.Singular(entityType)
csvPF = CSVPrintFile([entityTypeName, 'resourceName'], 'sortall') if Act.csvFormat() else None csvPF = CSVPrintFile([entityTypeName, 'resourceName'], 'sortall') if Act.csvFormat() else None
if csvPF: if csvPF:
csvPF.SetEscapeChar(None) csvPF.SetNoEscapeChar(True)
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
fieldsList = [] fieldsList = []
parameters = _initPersonMetadataParameters() parameters = _initPersonMetadataParameters()
@ -26376,7 +26397,7 @@ def doPrintShowChromePolicies():
customer = _getCustomersCustomerIdWithC() customer = _getCustomersCustomerIdWithC()
csvPF = CSVPrintFile(CHROME_POLICY_SORT_TITLES, indexedTitles=CHROME_POLICY_INDEXED_TITLES) if Act.csvFormat() else None csvPF = CSVPrintFile(CHROME_POLICY_SORT_TITLES, indexedTitles=CHROME_POLICY_INDEXED_TITLES) if Act.csvFormat() else None
if csvPF: if csvPF:
csvPF.SetEscapeChar(None) csvPF.SetNoEscapeChar(True)
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
appId = orgUnit = policySchemaFilter = printerId = None appId = orgUnit = policySchemaFilter = printerId = None
showPolicies = CHROME_POLICY_SHOW_ALL showPolicies = CHROME_POLICY_SHOW_ALL
@ -26783,13 +26804,13 @@ def getCIDeviceEntity():
pageMessage = getPageMessage() pageMessage = getPageMessage()
try: try:
devices = callGAPIpages(ci.devices(), 'list', 'devices', devices = callGAPIpages(ci.devices(), 'list', 'devices',
throwReasons=[GAPI.INVALID, GAPI.PERMISSION_DENIED], throwReasons=[GAPI.INVALID, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS, retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
pageMessage=pageMessage, pageMessage=pageMessage,
customer=customer, filter=query, customer=customer, filter=query,
fields='nextPageToken,devices(name)', pageSize=100) fields='nextPageToken,devices(name)', pageSize=100)
return (devices, ci, customer, False) return (devices, ci, customer, False)
except GAPI.invalid: except (GAPI.invalid, GAPI.invalidArgument):
Cmd.Backup() Cmd.Backup()
usageErrorExit(Msg.INVALID_QUERY) usageErrorExit(Msg.INVALID_QUERY)
except GAPI.permissionDenied as e: except GAPI.permissionDenied as e:
@ -27121,11 +27142,13 @@ DEVICE_FIELDS_CHOICE_MAP = {
'buildnumber': 'buildNumber', 'buildnumber': 'buildNumber',
'compromisedstate': 'compromisedState', 'compromisedstate': 'compromisedState',
'createtime': 'createTime', 'createtime': 'createTime',
'deviceid': 'deviceId',
'devicetype': 'deviceType', 'devicetype': 'deviceType',
'enableddeveloperoptions': 'enabledDeveloperOptions', 'enableddeveloperoptions': 'enabledDeveloperOptions',
'enabledusbdebugging': 'enabledUsbDebugging', 'enabledusbdebugging': 'enabledUsbDebugging',
'encryptionstate': 'encryptionState', 'encryptionstate': 'encryptionState',
'endpointverificationspecificattributes': 'endpointVerificationSpecificAttributes', 'endpointverificationspecificattributes': 'endpointVerificationSpecificAttributes',
'hostname': 'hostname',
'imei': 'imei', 'imei': 'imei',
'kernelversion': 'kernelVersion', 'kernelversion': 'kernelVersion',
'lastsynctime': 'lastSyncTime', 'lastsynctime': 'lastSyncTime',
@ -69278,7 +69301,7 @@ NOTES_ROLE_CHOICE_MAP = {
def printShowNotes(users): def printShowNotes(users):
csvPF = CSVPrintFile(['User', 'name', 'title', 'owner', 'ownedByMe']) if Act.csvFormat() else None csvPF = CSVPrintFile(['User', 'name', 'title', 'owner', 'ownedByMe']) if Act.csvFormat() else None
if csvPF: if csvPF:
csvPF.SetEscapeChar(None) csvPF.SetNoEscapeChar(True)
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
compact = False compact = False
fieldsList = [] fieldsList = []
@ -69860,7 +69883,7 @@ def printShowTasks(users):
csvPF = CSVPrintFile(['User', 'tasklistId', 'id', 'taskId', 'title', 'status', 'due', 'updated', 'completed'], 'sortall') if Act.csvFormat() else None csvPF = CSVPrintFile(['User', 'tasklistId', 'id', 'taskId', 'title', 'status', 'due', 'updated', 'completed'], 'sortall') if Act.csvFormat() else None
if csvPF: if csvPF:
csvPF.SetEscapeChar(None) csvPF.SetNoEscapeChar(True)
CSVTitle = 'Tasks' CSVTitle = 'Tasks'
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
tasklistEntity = None tasklistEntity = None
@ -70092,7 +70115,7 @@ def processTasklists(users):
def printShowTasklists(users): def printShowTasklists(users):
csvPF = CSVPrintFile(['User', 'id', 'title']) if Act.csvFormat() else None csvPF = CSVPrintFile(['User', 'id', 'title']) if Act.csvFormat() else None
if csvPF: if csvPF:
csvPF.SetEscapeChar(None) csvPF.SetNoEscapeChar(True)
CSVTitle = 'TaskLists' CSVTitle = 'TaskLists'
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
countsOnly = False countsOnly = False