Twitter

Some bash tips -- 18 -- paste

This blog is part of a shell tips list which are good to know -- the whole list can be found here.

I really like finding a real usage for a Unix command you heard of, you have somewhere in your quiver but you never really used because you never found an opportunity to or you never found the good combo which makes it very powerful. Let's explore the power of paste which we will end up combining with fold, shuf and column.

First, let's generate a simple list of numbers, one number per line using seq:
$ seq 1 7
1
2
3
4
5
6
7
$
Now let's say you want to organize these numbers by columns of two numbers. Hmmm not that easy right? this where paste shines:
$ seq 1 7 | paste - -
1       2
3       4
5       6
7
$
See these 2 hyphens in paste - -? There are the number of columns you want paste to organize your data in; you want 4 columns? just use 4 hyphens:
$ seq 1 7 | paste - - - - 
1       2       3       4
5       6       7
$
It also makes very easy something oftenly hapenning: rows to columns. paste has the -s/--serial option for that, check below:
$ seq 1 7 | paste -s
1       2       3       4       5       6       7
$
Pretty cool, right? And maybe a CSV type output would be a very good idea as well. paste also got you covered; Indeed, by default paste uses a TAB as a separator which we can change using -d/--delimiters:
$ seq 1 7 | paste -s -d ","
1,2,3,4,5,6,7
$
And what about a CSV with 2 columns per line?
$ seq 1 7 | paste - -  -d ","
1,2
3,4
5,6
7,
$
Note that all of that also works from a file as well:
$ seq 1 7 > test_file
$ cat test_file | paste - -  -d ","
1,2
3,4
5,6
7,
$
Cool but what about a real life example. Let's say we want to create a nice table like list of our OCI Autonomous Databases. The command to get that would be:
$ oci search resource structured-search --limit 1000 --query-text "query AutonomousDatabase resources return allAdditionalFields where lifecyclestate != 'TERMINATED'" |
$
This would generate a JSON with tons (too much) of information and JSON is not really human readable. We could then first use jq to only get the information we are interested in:
$ oci search resource structured-search --limit 1000 --query-text "query AutonomousDatabase resources return allAdditionalFields where lifecyclestate != 'TERMINATED'" | jq -r '.data.items[] | ."additional-details".dbName,."additional-details".ecpuCount,."additional-details".workloadType, ."additional-details".dataStorageSizeInTBs,."lifecycle-state", (."time-created" | gsub("[.][0-9].*$";""))'
PROD2
32.0
ATP
8
AVAILABLE
2024-09-02T07:49:32
PROD1
64.0
ADW
0
AVAILABLE
2023-12-06T02:20:58
TEST1
48.0
ADW
0
AVAILABLE
2023-11-29T02:07:21
$
We indeed get the information we need but it is not really readable. I guess you already guessed how to make it readable: paste! We have 6 values per Autonomous Database, so just use 6 hypens in the paste command:
$ oci search resource structured-search --limit 1000 --query-text "query AutonomousDatabase resources return allAdditionalFields where lifecyclestate != 'TERMINATED'" | jq -r '.data.items[] | ."additional-details".dbName,."additional-details".ecpuCount,."additional-details".workloadType, ."additional-details".dataStorageSizeInTBs,."lifecycle-state", (."time-created" | gsub("[.][0-9].*$";""))' | paste - - - - - -
PROD2        32.0    ATP     8       AVAILABLE       2024-09-02T07:49:32
PROD1        64.0    ADW     0       AVAILABLE       2023-12-06T02:20:58
TEST1        48.0    ADW     0       AVAILABLE       2023-11-29T02:07:21
$
Oh, this is very better! One would tell me that we can also do that using jq using join or @tsv and you would be correct but paste will work with non JSON outputs.

You also know that you can easily add a -d "," to get that output in CSV but let's keep it text based as I want that list from my terminal on my VM quickly when I need it and I would like that output to be nicer. This is where column comes into play! column makes nice columns (adapting the size of the columns) from outputs and can also add some nice column separators to look like a table (I won't re show the whole long oci | jq command for viibility):
$ oci search . . . | paste - - - - - - | sort | column -t -o " | "
PROD1 | 64.0 | ADW | 0 | AVAILABLE | 2023-12-06T02:20:58
PROD2 | 32.0 | ATP | 8 | AVAILABLE | 2024-09-02T07:49:32
TEST1 | 48.0 | ADW | 0 | AVAILABLE | 2023-11-29T02:07:21
$
column can also add a header for each column:
$ oci search . . . | paste - - - - - - | sort | column -t -o " | " -N "DBName,ECPU,Type,TBs,Status,TimeCreated"
DBName | ECPU | Type | TBs | Status    | TimeCreated
PROD1  | 64.0 | ADW  | 0   | AVAILABLE | 2023-12-06T02:20:58
PROD2  | 32.0 | ATP  | 8   | AVAILABLE | 2024-09-02T07:49:32
TEST1  | 48.0 | ADW  | 0   | AVAILABLE | 2023-11-29T02:07:21
$
Last but not least, it is also easy to hide columns; let's hide the ECPU (column2) and the TBs (column 4) numbers (by the way, I contacted support as the TBs for my ADW is 0 which looks like a bug):
$ oci search . . . | paste - - - - - - | sort | column -t -o " | " -N "DBName,ECPU,Type,TBs,Status,TimeCreated" -H2,4
DBName | Type | Status    | TimeCreated
PROD1  | ADW  | AVAILABLE | 2023-12-06T02:20:58
PROD2  | ATP  | AVAILABLE | 2024-09-02T07:49:32
TEST1  | ADW  | AVAILABLE | 2023-11-29T02:07:21
$
Super cool and super easy!

Now, let's get back to another good combo using paste. We sometimes need to anonymize data (when writing a blog for example) and this can be a bit painful; what if we could have a tool automatically shuffling the characters of what we want to anonymize for us? Let's go back to our sequence of 7 numbers I opened with and we let's use the shuf command which will shuffle the lines of this output:
$ seq 1 7 | shuf
4
7
2
5
1
6
3
$
We now automatically recognize the kind of input which can be serialized by paste; let's do it:
$ seq 1 7 | shuf | paste -s -d ''
1547362
$
Note: the output is always different as shuf will shuffle the data differently each time it is executed. This is very cool, we now just need to find something which transform a list of characters to one character per line (indeed, we won't use seq but real data to be anonymized); a kind of unpaste command; as usual, those crazy Unix creators thought about everything and this command is... fold which wraps lines up to a number of character which we can set to 1 for our need:
$ echo "1234567"
1234567
$echo "1234567" | fold -w 1
1
2
3
4
5
6
7
$
We now have the combo we wanted:
$ echo "1234567" | fold -w 1 | shuf | paste -s -d ''
5347162
$ echo "1234567" | fold -w 1 | shuf | paste -s -d ''
3746215
$ echo "1234567" | fold -w 1 | shuf | paste -s -d ''
7253416
$
You have here a string anonymizer; if you use that on an OCID for example:
$ echo "anuwcljt6ubcb2aa6hv52fnv343cvqhvwit7fedl4q7beqd2gw2fkhr4mhma" | fold -w 1 | shuf | paste -s -d ''
4cqah43jdkv23uqu2l22thmlwvrbqbawhnf4ncevewfgh5f6atmb7dvc6i7a
$
Well, good luck to find the original one back!

And all of this for ~ 100 KB:
$ du -sh /usr/bin/shuf
48K     /usr/bin/shuf
$ du -sh /usr/bin/fold
36K     /usr/bin/fold
$ du -sh /usr/bin/paste
36K     /usr/bin/paste
$
Now that you've learnt how to make some cool combos with paste, fold, shuf and column, ask the below question to your colleagues:


That's all for this one; enjoy and... keep it simple!
< Previous shell tip / Next shell tip coming soon >

OCI: Database Link between 2 Autonomous Databases

Database links are seen by some as evil and as wonderful tools by others. Whatever your side on this, let's see how we can create database links between 2 autonomous databases. The characteristics of the below example are:
  • We want to get data from the PROD1 database
  • The database link will be created into the PROD2 database
  • A network connectivity is already setup between the databases; the ones in this example are in the same tenancy and in the same region; if your databases are in different tenancies, you want to check this documentation first; if they are in different regions, you please have a look at this documentation first
  • The databases can be in the same compartment or not; below example is with 2 databases in different compartments
  • The autonomous databases can be ADW or ATP, it does not matter
  • I will use one and unique Linux VM with a non privileged user fred@myvm on that VM
  • Many operations are only doable by the ADMIN user so be sure you know the ADMIN user credentials
  • Below assumes that your OCI client is configured and works

A summary of what needs to be done looks straigthforward on a graph:
But the fact that these are autonomous databases implies many steps which I will be describing in this blog.
Let's follow and detail each of the steps shown on the above picture.

0/ Requirements summary

A short summary of the requirements to be able to create a DB Link:
  • Network connectivity between the 2 databases
  • A database username and password on PROD1
  • The PROD1 database certificate
  • OCIDs of PROD1, PROD2, your compartments, etc...

1/ Get the PROD1 wallet

Ge the PROD1 database OCID from the console and use it to get the database wallet from your Linux VM:
[fred@myvm ~] oci db autonomous-database generate-wallet --autonomous-database-id ocid1.autonomousdatabase.oc1.iad.xxx --file adb_wallet.zip --password "abc123456"
Downloading file  [####################################]  100%
[fred@myvm ~] ls -ltr adb_wallet.zip
-rw-rw-r--. 1 fred fred 21974 Sep 30 13:05 adb_wallet.zip
[fred@myvm ~]
Note that we must specify a wallet password using this oci db autonomous-database generate-wallet command; related error message you would face (I tried :)) are:
Error: Missing option(s) --password.
"message": "The wallet download password cannot be an empty string.",
"message": "The wallet download password must be at least 8 characters.",
You can also download this wallet from the console: "Autonomous database details" => "Database connection" => "Download wallet"; we won't use this password so feel free to forget that password immediately! Let's unzip the wallet and points the files we will be interested in:
[fred@myvm ~] unzip adb_wallet.zip
Archive:  adb_wallet.zip
  inflating: ewallet.pem
  inflating: README
  inflating: cwallet.sso     <== the certificate we will work with
  inflating: tnsnames.ora    <== we will need host, service and port information at the end of the procedure
  inflating: truststore.jks
  inflating: ojdbc.properties
  inflating: sqlnet.ora
  inflating: ewallet.p12
  inflating: keystore.jks
[fred@myvm ~]
All right, step 1 was easy, let's jump into step 2.

2/ Transfer the certificate

This one looks simple but many steps are needed to achieve the transfer of the certificate; indeed, we have to transfer the PROD1 cwallet.sso file into a PROD2 directory (DBFS). The steps to achieve that are:
  • 2.1/ Create a bucket (unless you already have one)
  • 2.2/ Copy the cwallet.sso file from your Linux VM into your bucket
  • 2.3/ Create a directory into the PROD2 database
  • 2.4/ Copy the cwallet.sso file from your bucket into the PROD2 PROD2 directory
  • 2.5/ Drop your bucket if you created one just for this transfer
And on top of that, we will need to create some credentials to get authenticated here and there. Yeaaaahh all of that just to copy a file . . . hopefully it is a one time thing :)

2.1/ Create a bucket (unless you already have one)

You'll find your PROD2 database compartment OCID in the console (search for "Compartment"):
[fred@myvm ~] oci os bucket create --name wallets --compartment-id ocid1.compartment.oc1..aaaaaaabbbbbbbbcccccccccccfffffffff  
{
    . . .
        "CreatedBy": "default/fred",
        "CreatedOn": "2024-09-30T13:07:25.850Z"
    . . .
    "name": "wallets",
    . . .
}
[fred@myvm ~]


2.2/ Copy the cwallet.sso file from your Linux VM into your bucket

[fred@myvm ~] oci os object put --bucket-name wallets --file cwallet.sso  
Uploading object  [####################################]  100%
{
  "etag": "9fba7327-d979-4b21-a898-8b795ea02f76",
  "last-modified": "Mon, 30 Sep 2024 13:09:42 GMT",
  "opc-content-md5": "sstACFWtW/4qBGNkdH/iuQ=="
}
 [fred@myvm ~]
Check that the file has been correctly copied into the wallet:
[fred@myvm ~] oci os object list --bucket-name wallets
{
  "data": [
      . . .
      "name": "cwallet.sso",
      . . .
}
[fred@myvm ~]


2.3/ Create a directory into the PROD2 database

Note that as of now only ADMIN can create directories and DB Links.
SQL> show user
USER is "ADMIN"
SQL> create directory wallets as 'wallets';
Directory created.
SQL> select OWNER, DIRECTORY_NAME, DIRECTORY_PATH from dba_directories where directory_name = 'WALLETS';
OWNER    DIRECTORY_NAME   DIRECTORY_PATH
-------- ---------------- --------------------------------------------------------------------------------
SYS      WALLETS          /u03/dbfs/0B3BHK09F13420009KP8/data/wallets
SQL>


2.4/ Copy the cwallet.sso file from your bucket into the PROD2 database directory

We now need to create somne credentials to achieve this. I use to go with "Auth tokens" which are kind of the same tokens you use for github if you are familiar with. You'll need your user-id which you can find in the console "Your profile" (top right) => "My profile" then copy your OCID in "User information" or in the ~/.oci/config file (grep user ~/.oci/config):
[fred@myvm ~] oci iam auth-token create --user-id ocid1.user.oc1..xxxx --description fred_cred_for_wallet_dblink
  {
  "data": {
    "description": "fred_cred_for_wallet_dblink",  <== it is actually the credential name
    . . .
    "token": "c]CBZfi97_E(;U5",                    <== your token
    "user-id": "ocid1.user.oc1..xxxx"
  },
  "etag": "89c91cb65f03452fabd74c618609d0bb"
}
[fred@myvm ~]
You can also use the console to get a token: "Your profile" (top right) => "My profile" => "Auth tokens" (bottom left) => "Generate token".

Now create the credentials (as ADMIN):
SQL> show user
USER is "ADMIN"
SQL> BEGIN
  2  DBMS_CLOUD.CREATE_CREDENTIAL(credential_name => 'fred_cred_for_wallet_dblink', username => 'fred', password => 'c]CBZfi97_E(;U5');
  3  END;
  4  /
PL/SQL procedure successfully completed.
SQL>
Note that I kept "c]CBZfi97_E(;U5')" as token instead of putting "xxxx"; it is to show what an Auth token looks like, it is obviously not my real token. Also, the user used here is the one you connect to your tenancy with the console so most likely your email address.

Now to copy the cwallet.sso file into the WALLETS directory, we need to know the path of that file; for now we just know that it is located into the wallets bucket. You can find this path from the console in "Object Details" on the right of the file when you list the content of your bucket. I could not find a way to get that info using the oci client, this is then an opportunity to learn how these paths are built and build it ourselves.

Object paths are of this form (I put shell variables in the path as this is how we're gonna build it):
https://${NAMESPACE}.objectstorage.${REGION}.oci.customer-oci.com/n/${NAMESPACE}/b/${BUCKET_NAME}/o/${FILE}
We can find these values as below:
[fred@myvm ~] NAMESPACE=$(oci os ns get | jq -r '.data')
[fred@myvm ~] REGION="us-ashburn-1"     <== this can be found in the ~/.oci/config file
[fred@myvm ~] BUCKET_NAME="wallets"
[fred@myvm ~] FILE="cwallet.sso"
[fred@myvm ~] echo "https://${NAMESPACE}.objectstorage.${REGION}.oci.customer-oci.com/n/${NAMESPACE}/b/${BUCKET_NAME}/o/${FILE}"
https://ihdfd7683hjkz.objectstorage.us-ashburn-1.oci.customer-oci.com/n/ihdfd7683hjkz/b/wallets/o/cwallet.sso
[fred@myvm ~]
And we get file path of the file! We can finally copy the cwallet.sso file from our bucket into the directory (DBFS)!
SQL> show user
USER is "ADMIN"
SQL> BEGIN
  2  DBMS_CLOUD.GET_OBJECT(
  3  object_uri => 'https://ihdfd7683hjkz.objectstorage.us-ashburn-1.oci.customer-oci.com/n/ihdfd7683hjkz/b/wallets/o/cwallet.sso',
  4  directory_name => 'WALLETS',
  5  credential_name => 'fred_cred_for_wallet_dblink');
  6  END;
  7  /
PL/SQL procedure successfully completed.
SQL> SELECT OBJECT_NAME, BYTES, CREATED, LAST_MODIFIED from DBMS_CLOUD.LIST_FILES('WALLETS');
OBJECT_NAME             BYTES CREATED                                            LAST_MODIFIED
------------------ ---------- ------------------------------------------------ ---------------------------------------------
cwallet.sso              5349 30-SEP-24 02.21.22.000000 PM +00:00                30-SEP-24 02.21.22.000000 PM +00:00
SQL>


2.5/ Drop your bucket if you created one just for this transfer

If you have created a dedicated bucket for this transfer, you may want to drop it to keep things clean, we won't need it anymore.
[fred@myvm ~] oci os bucket delete --name wallets
Are you sure you want to delete this bucket? [y/N]: y
[fred@myvm ~]


3/ Create the DB Link

OK! we can now create the DB Link -- after we create some more credentials: the credentials to connect to the PROD1 database:
SQL> BEGIN
2  DBMS_CLOUD.CREATE_CREDENTIAL(credential_name => 'PROD1_USER', username => 'A_PROD1_USER', password => 'xxxxxxxxxx');
3  END;
4  /
PL/SQL procedure successfully completed.
SQL>
And (finally !) create the DB Link. You'll need the below information from the tnsnames.ora file from the wallet we generated during step 1:
  • hostname => xxxxxxx.adb.us-ashburn-1.oraclecloud.com
  • port => 1522
  • service_name => yyyyyyy.adb.oraclecloud.com
SQL> BEGIN
  2  DBMS_CLOUD_ADMIN.CREATE_DATABASE_LINK(
  3  db_link_name => 'TO_PROD1',
  4  hostname => 'xxxxxxx.adb.us-ashburn-1.oraclecloud.com',
  5  port => '1522',
  6  service_name => 'yyyyyyy.adb.oraclecloud.com',
  7  credential_name => 'PROD1_USER',
  8  directory_name => 'WALLETS',
  9  private_target => TRUE,
 10  public_link => TRUE);
 11  END;
 12  /
PL/SQL procedure successfully completed.
SQL>


And now the moment of truth: testing the DB Link !
SQL> select count(*) from user_objects@SOURCE_DATABASE;
  COUNT(*)
----------
      1994
SQL>


Congratulations, now go enjoy your new DB Link between your 2 autonomous databases!

OCI: Setting up API Keys

GUI interfaces are nice and beautiful but they are usually less efficient than the command line. Let's explore how to set up API Keys in OCI (Oracle Cloud Infrastructure) to be able to use the command line instead of the OCI Console.

First of all, we need to have the oci-cli installed which is installed by default on OCI VMs:
[fred@myvm ~]$ type oci
oci is /usr/local/bin/oci
[fred@myvm ~]$ oci --version
3.47.0
[fred@myvm ~]$
If it is not installed on your system, the install doc can be found here for all the supported systems, it takes a minute.
So let's start by, let's say, try to create a bucket using the command line (you'l find the compartment id of the compartment you want to create your bucket in the compartment page, just seach for "compartment" in the OCI console):
[fred@myvm ~]$ oci os bucket create --name this_is_my_bucket --compartment-id gdsgshdsgbjgfjhfgdhfgdsjhgdjhgdfjds
ERROR: Could not find config file at /home/fred/.oci/config
Do you want to create a new config file? [Y/n]: n
[fred@myvm ~]$
So we are asked for a ~/.oci/config file which does not exist by default; we are also offered to create a new one; I would recommend saying no to this question, the following procedure seems awkward to me. Let's create that ~/.oci/config file manually instead.

First, on the top right of the OCi console, click on your profile and "My Profile":
Then, on the bottom left, on "API Keys" and "Add API Key":
Here, you have to download your private key (and do not lose it) -- as mentioned, this is the only time you could do it so keep it safe:
Now is shown to you the content you need to copy into that ~/.oci/config configuration file on your VM:
Let's create this ~/.oci directory and this ~/.oci/config file:
[fred@myvm ~]$ mkdir ~/.oci
[fred@myvm ~]$ vi ~/.oci/config
[fred@myvm ~]$ cat ~/.oci/config
[DEFAULT]
user=ocid1.user.oc1..aaaaaabbbbbccccccccccdddddddddddeeeeeeee
fingerprint=66:xxxxxxxxxxxxxxxxx
tenancy=ocid1.tenancy.oc1.. aaaaaabbbbbccccccccccdddddddddddeeeeeeee
region=us-ashburn-1
key_file=~/.oci/fred_myvm.key
[fred@myvm ~]$
So here I have just pasted in ~/.oci/config the content I copied from the OCI console. There is only one thing to update is to point the key_file parameter to a file which contain the private key you have downloaded in the previous step; you can name this file with whatever name and extension but keep it in the ~/.oci directory. You can just open the private key you have previously downloaded and paste it in the file:
[fred@myvm ~]$ vi ~/.oci/fred_myvm.key
[fred@myvm ~]$
Same as SSH, these files are very strict on permission, thanksfully, Oracle provides a tool which sets everything correctly for us:
[fred@myvm ~]$ oci setup repair-file-permissions --file /home/fred/.oci/config
[fred@myvm ~]$ ls -altr ~/.oci
total 8
-rw-------. 1 fred fred  290 Sep 26 12:28 config
-rw-------. 1 fred fred 1716 Sep 26 12:29 fred_myvm.key
drwx------. 4 fred fred  123 Sep 26 12:29 ..
drwxrwxr-x. 2 fred fred   41 Sep 26 12:29 .
[fred@myvm ~]$
Let's nor retry to create a bucket!
[fred@myvm ~]$ oci os bucket create --name this_is_my_bucket --compartment-id ocid1.compartment.oc1..gdsgshdsgbjgfjhfgdhfgdsjhgdjhgdfjds
{
  "data": {
    "approximate-count": null,
    . . .
    "metadata": {},
    "name": "this_is_my_bucket",
    "namespace": "xxxxx",
    . . .
    "time-created": "2024-09-26T12:35:47.425000+00:00",
  . . .
}
[fred@myvm ~]$
Very cool, we have created a bucket using the command line. Note that I didn't need to specify any profile in my command line as the API keys I added in my ~/.oci/config are in the DEFAULT profile (by the way, profile names are key sensitive and the default one is DEFAULT and not default):
[fred@myvm ~]$ cat ~/.oci/config
[DEFAULT]
user=ocid1.user.oc1..aaaaaabbbbbccccccccccdddddddddddeeeeeeee
fingerprint=66:xxxxxxxxxxxxxxxxx
tenancy=ocid1.tenancy.oc1.. aaaaaabbbbbccccccccccdddddddddddeeeeeeee
region=us-ashburn-1
[fred@myvm ~]$
Note that you can change this which would allow you to use many different configurations to being able to connect to different tenancies from the same OS user or connect to different users (with different privileges) to the same tenancy:
[fred@myvm ~]$ cat ~/.oci/config
[PROD1]
user=ocid1.user.oc1..aaaaaabbbbbccccccccccdddddddddddeeeeeeee
fingerprint=66:xxxxxxxxxxxxxxxxx
tenancy=ocid1.tenancy.oc1..aaaaaabbbbbccccccccccdddddddddddeeeeeeee
region=us-ashburn-1
[PROD2]
user=ocid1.user.oc1..xxxxxxxxxyyyyyyyzzzzzzzzzzz
fingerprint=66:zzzzzzzzzzz
tenancy=ocid1.tenancy.oc1..xxxxxxxxxyyyyyyyzzzzzzzzzzz
region=us-ashburn-1
[fred@myvm ~]$
Above shows a configuration pointing to 2 different tenancies: PROD1 and PROD2. Let's say I created the bucket above in PROD1, I now have to specificy the profile to use as there is no default anymore:
[fred@myvm ~]$ oci os object list --all --bucket-name this_is_my_bucket
ERROR: The config file at ~/.oci/config is invalid:
+Config Errors+---------+----------------------------------------------------------------------------------+
| Key         | Error   | Hint                                                                             |
+-------------+---------+----------------------------------------------------------------------------------+
| user        | missing | log into the console and go to the user's settings page to find their OCID       |
| fingerprint | missing | openssl rsa -pubout -outform DER -in  | openssl md5 -c |
| key_file    | missing | the full path and filename of the private PEM key file                           |
| region      | missing | for example, us-phoenix-1                                                        |
| tenancy     | missing | log into the console and find this OCID at the bottom of any page                |
+-------------+---------+----------------------------------------------------------------------------------+
[fred@myvm ~]$ oci os object list --all --bucket-name this_is_my_bucket --profile PROD1
{
  "prefixes": []   <== there is nothing in my bucket which is expected
}
[fred@myvm ~]$
Unfortunately, you cannot add more to that ~/.oci/config file; it would indeed by handy for example to be able to add the compartment-id not to have to specift it in all the command lines which require it but it may come later, who knows.

Last but not least, mind that any oci command line has a --help option which will show you any possible option; this is pretty well documented:
[fred@myvm ~]$ oci --help
. . .
[fred@myvm ~]$ oci os bucket create --help
. . .
[fred@myvm ~]$
Let's drop that example bucket to keep things clean:
[fred@myvm ~]$ oci os bucket delete --name this_is_my_bucket --profile PROD1
Are you sure you want to delete this bucket? [y/N]: y
[fred@myvm ~]$
And you are now ready ot use the OCI command line!

Some bash tips -- 18 -- paste

This blog is part of a shell tips list which are good to know -- the whole list can be found here. I really like finding a real usage for...