{"id":21445776,"url":"https://github.com/sensenet/sn-io","last_synced_at":"2026-02-12T07:36:38.204Z","repository":{"id":46423179,"uuid":"388112444","full_name":"SenseNet/sn-io","owner":"SenseNet","description":"Import and export features and tools for the sensenet repository.","archived":false,"fork":false,"pushed_at":"2025-03-06T13:52:14.000Z","size":247,"stargazers_count":0,"open_issues_count":4,"forks_count":0,"subscribers_count":4,"default_branch":"develop","last_synced_at":"2025-11-27T18:28:45.116Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SenseNet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-07-21T12:39:51.000Z","updated_at":"2025-03-06T13:52:17.000Z","dependencies_parsed_at":"2024-02-02T10:48:17.081Z","dependency_job_id":"4c46eef4-3ce6-4e66-b37b-f1ae022cf771","html_url":"https://github.com/SenseNet/sn-io","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/SenseNet/sn-io","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SenseNet%2Fsn-io","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SenseNet%2Fsn-io/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SenseNet%2Fsn-io/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SenseNet%2Fsn-io/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SenseNet","download_url":"https://codeload.github.com/SenseNet/sn-io/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SenseNet%2Fsn-io/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29361613,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T01:03:07.613Z","status":"online","status_checked_at":"2026-02-12T02:00:06.911Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-23T02:38:43.409Z","updated_at":"2026-02-12T07:36:38.189Z","avatar_url":"https://github.com/SenseNet.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SnIO: Import and export for the sensenet repository\nSnIO is a library and command line tool designed to help operators and developers copying content from and to a content repository. It is able to connect to a sensenet content repository service through _http_ and download/upload content items - or even copy content items between two repositories directly.\n\nThe source and target are completely independent - either of them can be a repository or the file system. You can define a subtree to export and filter the source so that only a subset of the content tree is exported.\n\n\u003e **Main use cases**: the SnIO tool is useful when you want to **archive** or **back up** content, want to **periodically update** content from a staging service to production. It is also useful if you have a predefined content structure you want to **import** on new sensenet instances.\n\n## Scenarios\nThere are four scenarios offered by the built-in tool.\n- **[EXPORT](#EXPORT)**: Transfer content from a sensenet repository to the file system.\n- **[IMPORT](#IMPORT)**: Transfer content from the file system to a sensenet repository.\n- **[COPY](#COPY)**: Transfer content between file system directories :).\n- **[SYNC](#SYNC)**: Transfer content from a sensenet repository to another repository.\n\n\u003e **For developers**: SnIO is extendable. You can extend our default content tree readers and writers, or implement your own. Currently you'll have to look into the source code for examples.\n\n## Installation\nYou can get the SnIO tool in the following ways:\n- integrate the [SenseNet.IO](https://www.nuget.org/packages/SenseNet.IO) NuGet package into your application and use our API to manage content in your repository\n- compile the source code in this repository and use the tool from the `SenseNet.IO.CLI` folder\n- **BETA**: install the tool as a [dotnet tool](https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools) from [NuGet](https://www.nuget.org/packages/SenseNet.IO.CLI) and use it anywhere from command line. The following command will install the sensenet IO tool as a global dotnet tool:\n\n`dotnet tool install -g sensenet.io.cli`\n\n[![NuGet](https://img.shields.io/nuget/v/SenseNet.IO.CLI.svg)](https://www.nuget.org/packages/SenseNet.IO.CLI)\n\n## Parameters\nThe SnIO tool has a number of parameters with some restrictions. The general form is the following:\n```\nSnIO \u003cScenario\u003e [General parameters] [-SOURCE \u003cSource parameters\u003e] [-TARGET \u003cTarget parameters\u003e]\n```\n\n\u003e For a full command line example with **authentication** please see the end of this article.\n\n### General parameters\nSnIO has its own configuration file, as you will see later in this article. All configured values can be overwritten using environment variables or in the command line using the usual .NET Core rules (see the [command-line arguments](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-5.0#command-line-arguments-1 \"Microsoft documentation\") and configuration in the .NET Core documentation).\n\n### Parameter name restrictions\n- Must start with the minus (`-`) character.\n- Cannot start with a slash (`/`) to avoid collisions because repository paths start with this character.\n- Case insensitive but here in the docs we write them in all capital letters for easier recognition.\n\n### Parameter sections\nThe source and target parameters are grouped into two sections. A section should start with `-SOURCE` or `-TARGET` and it ends with another section or end of the parameter list. Sections are interchangeable.\n\nThe default source and target parameters can be configured (see below).\nIf all section parameters are configured or default, the section selector is optional.\n\nSection parameters have a default order (see under every scenario below). If the order is followed - parameters are not swapped and there is no missing item between parameters - parameter names are optional. In the following example all source parameters are given in the right order (url, path, blocksize):\n```\nSnIO EXPORT -SOURCE \"https://example.sensenet.cloud\" \"/Root/Content\" 50\n```\nIn the next example the url is omitted (the configured default is used). In this case the first parameter is missing, so the parameter names are required.\n```\nSnIO EXPORT -SOURCE -PATH \"/Root/Content\" -BLOCKSIZE 50\n```\nConsidering the rules above, the simplest parameterization is the empty scenario, if all parameters are configured or default:\n```\nSnIO EXPORT\n```\n### Help screens\nIf the parameter list contains a question mark or the `-HELP` parameter, the help screen will be displayed. The help switch can also be used after a scenario keyword. In that case only the scenario's help screen will appear. The main help screen command alternatives:\n```\nSnIO ?\nSnIO -?\nSnIO -HELP\n```\nScenario help commands:\n```\nSnIO IMPORT ?\nSnIO IMPORT -?\nSnIO IMPORT -HELP\n```\n\n## EXPORT\nCopies a subtree from a sensenet repository to the file system. The source repository is defined only by a single URL, it can be hosted anywhere.\n\n\u003e **Authentication**: the tool has to have access to the source repository. See details in the [Authentication](#Authentication) section below.\n\nThe target file system directory will be created if it does not exist. If it does and it contains content items, the transferred material will be merged with the existing files. Existing content files will remain intact if the `-FLATTEN` parameter is used, otherwise they will be overwritten.\n\n### Source parameters\n1. **URL**: Url of the source sensenet repository e.g. 'https://example.sensenet.cloud'.\n2. **PATH**: Repository path of the root content of the tree to transfer. Default: '/Root'.\n3. **FILTER**: Filter the selected subtree. The filter is written in the [Content Query Language](https://docs.sensenet.com/api-docs/querying) format. Only terms and logical operators are effective, keywords (.TOP, .SKIP, .SORT etc.) are omitted.\n4. **BLOCKSIZE**: Count of items in one request. Default: 10.\n\n### Target parameters\n1. **PATH**: Fully qualified path of a target file system directory.\n2. **NAME**: Name of the target tree root if it is different from the source name.\n3. **FLATTEN**: Boolean switch without a parameter value. If it is provided, every content will be written into the same target file system directory. Files with the same name will be renamed (suffixed with a number). The original name and path can be found in the `*.Content` metafiles. _Warning_: flattening a big result set can degrade the writing performance.\n\n### Examples\n```\nSnIO EXPORT -SOURCE \"https://example.sensenet.cloud\" \"/Root/Content\" -TARGET \"D:\\Backup\\example.sensenet.cloud\"\n```\nAs a result the following file system entry appears: `D:\\Backup\\example.sensenet.cloud\\Content` and under that the whole subtree's content items in the same folder structure as in the repository.\n\nThe subtree can also be saved with another name (see the last parameter):\n```\nSnIO EXPORT -SOURCE \"https://example.sensenet.cloud\" \"/Root/Content\" -TARGET \"D:\\Backup\\example.sensenet.cloud\" -NAME \"OldContents\"\n```\nIn this case the new root file system entry is: `D:\\Backup\\example.sensenet.cloud\\OldContents`.\n\nA common scenario is exporting a subset of content items from a developer repository and importing it to another. The following command exports all items that were modified in the last 7 days (source url and path are configured):\n```\nSnIO EXPORT -SOURCE -FILTER \"ModificationDate:\u003e@@Today-7@@\" -TARGET \"D:\\Release\\example.sensenet.cloud\"\n```\n\nIf the goal is to collect filtered results in one place, use the filter and the flattening:\n```\nSnIO EXPORT -SOURCE \"https://example.sensenet.cloud\" \"/Root/Content\" \"+TypeIs:File +Name:My*\" -TARGET \"D:\\Backup\\MyFiles\" -FLATTEN\n```\nThis command copies all files starting with \"My\" to the \"MyFiles\" folder.\n\n## IMPORT\nCopies a subtree from the file system to a sensenet repository.\n\n\u003e **Authentication**: the tool has to have access to the target repository. See details in the [Authentication](#Authentication) section below.\n\nThe target container will be created if it does not exist. If it does, the transferred content items will be merged, existing contents will be \"patched\" (only the pushed fields will change).\n\n### Source parameters\n1. **PATH**: Fully qualified path of the file system entry to read.\n2. **SKIP**: Relative repository-style path list of skipped subtrees, e.g. `\"Content/F1\",\"IMS/BuiltIn\",\"System/Schema/ContentTypes\"`\n\n### Target parameters\n1. **URL**: Url of the target sensenet repository, e.g. 'https://example.sensenet.cloud'.\n2. **PATH**: Repository path of the target container. Default: '/'.\n3. **NAME**: Name of the target tree root if it is different from the source name.\n4. **CREATEONLY**: Boolean switch without a parameter value. If it is provided, only the new contents are transferred, updates are omitted.\n\n### Examples\nThe following example restores a backup material. Note that the source and target names are different. Parameter names are optional because the parameters are ordered as specified.\n```\nSnIO IMPORT -SOURCE \"D:\\Backup\\example.sensenet.cloud\\Content_2021-09-27\" -TARGET \"https://example.sensenet.cloud\" \"/Root\" \"Content\"\n```\nIf you want to skip some subtrees of a large material, you can use the SKIP parameter. In the example below, we omit a few subtrees from the import. Note that the main path is the fully qualified file-system path but the skip list contains repository-style relative paths.\n```\nSnIO IMPORT -SOURCE -PATH \"D:\\Backup\\example.sensenet.cloud\\Content_2021-09-27\" -SKIP \"Content/F1;System/Schema;IMS/BuiltIn\" -TARGET \"https://example.sensenet.cloud\" \"/Root\" \"Content\"\n```\n\n## COPY\nCopies a subtree from the file system to another directory in the file system.\n\nThe target file system directory will be created if it does not exist. If it does, transferred items will be merged, existing file system entries will be overwritten.\n\n### Source parameters\nSee the source parameters of the IMPORT scenario.\n\n### Target parameters\nSee the target parameters of the EXPORT scenario.\n\n## SYNC\nCopies a subtree from a sensenet repository to another sensenet repository.\n\nThe target container will be created if it does not exist. If it does, transferred material will be merged, existing contents will be \"patched\" (only the pushed fields will change).\n\n### Source parameters\nSee the source parameters of the EXPORT scenario.\n\n### Target parameters\nSee the target parameters of the IMPORT scenario.\n\n## Configuration\nThe SnIO tool uses two config files. The first is the default `appsettings.json`. It contains the general configuration of display appearance and logging. The second is `providerSettings.json` that contains the default parameter values of the built-in SnIO providers.\n### appsettings.json\n#### display.level\nThis section controls the details of writing to the console. There is only one value: `level`. Valid values: \"None\", \"Progress\", \"Errors\", \"Verbose\". Default: \"Errors\".\n\n```json\n{\n  \"display\": {\n    \"level\": \"Errors\"\n  }\n}\n```\n\n### Serilog\nThis app uses the [Serilog](https://serilog.net/ \"Serilog official site\") package for logging. See it's documentation [here](https://github.com/serilog/serilog/wiki \"Serilog wiki\").\n\n### Examples\nIn these examples configuration values will be overwritten in the command line using the .NET Core \"full-path\" form.\n\nParts of appsettings.json\n```json\n{\n  \"display\": {\n    \"level\": \"Errors\"\n  },\n  \"Serilog\": {\n    /* ... */\n    \"WriteTo\": [\n      {\n        \"Name\": \"File\",\n        \"Args\": {\n          \"path\": \"logs/SenseNet.IO-.txt\",\n          \"rollingInterval\": \"Day\"\n        }\n      }\n    ]\n  }\n}\n```\nIn the firs example the `display.level` is overwritten to display detailed information:\n```\nSnIO EXPORT --DISPLAY:LEVEL Verbose -SOURCE -PATH \"/Root/Content\"\n```\nIn the second example the log-file name pattern will be changed (consider that an array is accessed by the index of the desired item):\n```\nSnIO EXPORT --Serilog:WriteTo:0:Args:path \"logs/SnIO-.txt\" -SOURCE -PATH /Root/IMS\n```\n\n### providerSettings.json\nSnIO scenarios always use two providers: one source and one target. In this version there are four providers available that can drive these scenarios. Here are the valid combinations:\n\n|            | SOURCE           | TARGET           |\n| ---------- | ---------------- | ---------------- |\n| **EXPORT** | repositoryReader | fsWriter         |\n| **IMPORT** | fsReader         | repositoryWriter |\n| **COPY**   | fsReader         | fsWriter         |\n| **SYNC**   | repositoryReader | repositoryWriter |\n\nThe providers have several parameters. To simplify SnIO usages, default values can be configured. Here is an annotated example:\n\n```json\n{\n  \"repositoryReader\": {\n    \"url\": \"https://localhost:44362\", // Source URL\n    \"path\": null, // Source path. Default: \"/Root\",\n    \"blockSize\": null // Contents per request. Default (null, 0 or less): 10. \n  },\n  \"repositoryWriter\": {\n    \"url\": \"https://localhost:44362\", // Target URL\n    \"path\": null, // Target path. Default: \"/\",\n    \"name\": null // Target name under the container. Default: name of the reader's root.\n  },\n  \"fsReader\": {\n    \"path\": \"D:\\\\_sn-io-test\\\\localhost_44362\\\\Root\" // Source root\n  },\n  \"fsWriter\": {\n    \"path\": \"D:\\\\_sn-io-test\\\\localhost_44362\", // Target container. Will be created if does not exists.\n    \"name\": null // Target name under the container. Default: name of the reader's root.\n  }\n}\n```\n\n## Authentication\nAuthenticating works the same way in case of the source and the target repository: it uses the same client/secret or API key technique other sensenet tools use. You provide the clientid and secret or api key values for the repository reader and/or writer in the configuration (or overwrite them in environment variables or command line) and let the tool get the auth token from the corresponding authority related to the sensenet content repository.\n\nTo obtain the necessary values, please log in to your repository on the admin ui and visit the [Security settings page](https://docs.sensenet.com/guides/settings/api-and-security). There are also OData actions that will let you manage these values. \n\n### Examples\n#### In command line\n```\nSnIO IMPORT -SOURCE \"d:\\import\" -TARGET -URL \"https://example.com\" -PATH \"/Root/Content\" -APIKEY \"...\" \n\nSnIO IMPORT -SOURCE \"d:\\import\" -TARGET -URL \"https://example.com\" -PATH \"/Root/Content\" -CLIENTID \"...\" -CLIENTSECRET \"...\"\n```\n#### In configuration\n```json\n{\n  \"repositoryReader\": {\n    \"Authentication\": {\n      \"ClientId\": \"...\",\n      \"ClientSecret\": \"...\",\n      \"ApiKey\": \"...\" \n    } \n  },\n  \"repositoryWriter\": {\n    \"Authentication\": {\n      \"ClientId\": \"...\",\n      \"ClientSecret\": \"...\", \n      \"ApiKey\": \"...\" \n    } \n  }\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsensenet%2Fsn-io","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsensenet%2Fsn-io","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsensenet%2Fsn-io/lists"}