Managing content Tags in Box using the CLI

Rui Barbosa
Box Developer Blog
Published in
5 min readMar 28, 2023

--

Use case

This article was inspired by a question on our forum:

I would like to maintain the tags assigned to Box in bulk, is there any good solution? I was considering a way to use Box CLI, but the description of the CSV template does not mention tags, so I am looking for a solution.

I want to change the tags assigned to files in bulk with CLI. (e.g. tagA→tagB)

The tools

For this use case, the Box CLI is in fact the appropriate tool for the job. However you could easily integrate tags related features into your applications using any of our SDK's, or even manage tags directly using our REST API.

For this demo I'm using the Box CLI configured as a JWT application. This implies there is a service user which has to impersonate --as-user myself.

To make it easier to display in a blog format, I'll use CSV file format, forcing me to process the file using common tools such as Excel or the sed operating system command. However the Box CLI can also work with JSON format.

To get started with our Box CLI, you can take a look at this guide.

Finally I'm using MacOS so I do have access to sed and my shell is zShell. Of course Box CLI can also be used with PowerShell, Bash, etc.

Experiment with what ever you feel comfortable with.

Searching for tags

Since I have Box CLI configured as a JWT app, let's check the service user and the user I need to put in the --as-user flag.

❯ box users:get --csv --fields id,name,login

type,id,name,login
user,20130487697,JWT,AutomationUser_1827756_bs5C1GfCgv@boxdevedition.com

And the list of users available:

❯ box users --csv --fields id,name,login

type,id,name,login
user,18662105676,Administrator,AppUser_1715931_Il2dcyHuqu@boxdevedition.com
user,18662356345,Administrator,AppUser_1715931_vt8XOps1Ff@boxdevedition.com
user,18661971368,Administrator,AppUser_1715931_xSifhdw6W7@boxdevedition.com
user,22240548078,Investment User,barduinor+inv@gmail.com
user,22240405099,Wealth User,barduinor+we@gmail.com
user,22240545678,Wholesale User,barduinor+wh@gmail.com
user,18622116055,Rui Barbosa,barduinor@gmail.com

The content for which I want to manage the tags is under user 18622116055 , so I'll use this user id on the --as-user flag.

Now let's list all files tagged with TAG-A .

Please note that the search engine is querying an indexed database of the content and it can take a few minutes to index new content, just in case you are searching for content that was just created.

❯ box search "TAG-A" --as-user 18622116055 \
--content-types tags \
--csv --fields type,id,name,tags

type,id,name,tags
file,1016206416109,sample1.cr2,"[""TAG-D"",""TAG-A""]"
file,1016197618492,sample1.heic,"[""TAG-E"",""TAG-A""]"
file,1016203876842,023A9785.CR3,"[""TAG-C"",""TAG-A""]"

The --content-type tags reduces the scope of the search to only tags, as opposed to search for the query string in name, description and content.

The --csv --fields type,id,name,tags , tells the Box CLI to output in CSV format and only show type, id, name, and tags.

I could also use the --json to get a JSON output:

❯ box search "TAG-A" --as-user 18622116055 \
--content-types tags \
--json --fields type,id,name,tags

[
{
"type": "file",
"id": "1016206416109",
"name": "sample1.cr2",
"tags": [
"TAG-D",
"TAG-A"
]
},
{
"type": "file",
"id": "1016197618492",
"name": "sample1.heic",
"tags": [
"TAG-E",
"TAG-A"
]
},
{
"type": "file",
"id": "1016203876842",
"name": "023A9785.CR3",
"tags": [
"TAG-C",
"TAG-A"
]
}
]

Manipulating content tags

Now suppose I want to add FOOBAR for the first file sample.cr2 , I could try this:

❯ box files:update 1016206416109 \
--as-user 18622116055 \
--tags "FOOBAR" \
--csv --fields type,id,name

type,id,name
file,1016206416109,sample1.cr2

The end result is:

❯ box search "TAG-A" --as-user 18622116055 \
--content-types tags \
--csv --fields type,id,name,tags

type,id,name,tags
file,1016206416109,sample1.cr2,"[""FOOBAR""]"
file,1016197618492,sample1.heic,"[""TAG-E"",""TAG-A""]"
file,1016203876842,023A9785.CR3,"[""TAG-C"",""TAG-A""]"

Probably not what you expected, the tags update must include all the tags that you want associated with he content. In practice what we did was to replace all existing tags, if any, by the tag FOOBAR

Let's put back the original tags for file sample1.cr2

❯ box files:update 1016206416109 \
--as-user 18622116055 \
--tags "TAG-D,TAG-A" \
--csv --fields type,id,name

type,id,name
file,1016206416109,sample1.cr2

And check the results:

❯ box search "TAG-A" --as-user 18622116055 \
--content-types tags \
--csv --fields type,id,name,tags

type,id,name,tags
file,1016206416109,sample1.cr2,"[""TAG-A"",""TAG-D""]"
file,1016197618492,sample1.heic,"[""TAG-E"",""TAG-A""]"
file,1016203876842,023A9785.CR3,"[""TAG-C"",""TAG-A""]"

Replacing TAG-A with TAG-B

Since we need the original complete tags of each file, we need to first dump the existing content tags into a file, change TAG-A with TAG-B , and then update the content with the new set of tags.

Saving to a file is simple, we can use the operating system operator > piping it to a new file, or the --save-to-file-path flag.

❯ box search "TAG-A" --as-user 18622116055 \
--content-types tags \
--csv --fields type,id,name,tags > tag-a-content.csv

Let's display the content:

❯ cat tag-a-content.csv

type,id,name,tags
file,1016206416109,sample1.cr2,"[""TAG-A"",""TAG-D""]"
file,1016197618492,sample1.heic,"[""TAG-E"",""TAG-A""]"
file,1016203876842,023A9785.CR3,"[""TAG-C"",""TAG-A""]"

We can import this into Excel, and it will look like this:

Imported CSV into Excel

You may have noticed the uncommon format of the tags in excel, and from our example above we know that the update must be set of comma separated tags. So we need to "massage" this file to be able to update the content in bulk.

Since I'm on a mac, I can just use the sed command. Using Excel you can do some clever find and replace, or use a formula to change the tag column.

❯ sed -e  "s/TAG-A/TAG-B/g" \
-e "s/\[\"\"//g" \
-e "s/\"\"\]//g" \
-e "s/\"\"\,\"\"/\,/g" \
./tag-a-content.csv > tag-a-content-modified.csv

With the result:

❯ cat tag-a-content-modified.csv

type,id,name,tags
file,1016206416109,sample1.cr2,"TAG-B,TAG-D"
file,1016197618492,sample1.heic,"TAG-E,TAG-B"
file,1016203876842,023A9785.CR3,"TAG-C,TAG-B"

Now that we replaced TAG-A with TAG-B , and have the correct format, we can just feed this file to the update command of Box CLI, using the --bulk-file-path flag.

❯ box files:update --as-user 18622116055 \
--bulk-file-path ./tag-a-content-modified.csv \
--csv --fields type,id,name,tags

[========================================] 100% | 3/3
type,id,name
file,1016206416109,sample1.cr2
file,1016197618492,sample1.heic
file,1016203876842,023A9785.CR3
All bulk input entries processed successfully.

The files have beed immediately updated:

Content on the Box app showing files with TAG-B

But remember search might take a few minutes to index the new tag.

Searching for TAG-B :

❯ box search "TAG-B" --as-user 18622116055 \
--content-types tags \
--csv --fields type,id,name,tags

type,id,name,tags
file,1016206416109,sample1.cr2,"[""TAG-D"",""TAG-B""]"
file,1016197618492,sample1.heic,"[""TAG-E"",""TAG-B""]"
file,1016203876842,023A9785.CR3,"[""TAG-C"",""TAG-B""]"

We're done!

What to learn more?

Visit our developer documentation site, and follow us in medium, and twitter to stay up-to-date.

Cheers!

--

--