Learn Azure CLI syntax differences in Bash, PowerShell and Cmd
Azure CLI commands can be executed in both Bash, PowerShell, and Windows command shell (Cmd) scripting languages. However, there are subtile scripting differences. In this tutorial step, learn how to create your first Azure Storage Account and format parameter values for all three scripting languages.
Prerequisites
- You completed the prerequisites to prepare your environment.
- You have access to a resource group with
contributor
or higher permissions at a resource group level.
Be aware of line continuation characters
Most Azure CLI documentation is written and tested in Bash using Azure Cloud Shell. One of the first things to remember when copying Azure CLI syntax is to verify the line continuation characters for your chosen scripting language as they aren't interchangeable.
scripting language | Line continuation character |
---|---|
Bash | Backslash (\ ) |
PowerShell | Backtick (` ) |
Cmd | Carrot (^ ) |
Tip
The Copy button in the upper right corner of Azure CLI code blocks removes the backslash (\
) and the backtick (`
) by design. If you want to copy a formatted code block, use your keyboard or mouse to select and copy the example.
Understand syntax differences when using variables
The syntax for using variables varies slightly between scripting languages. Here's a comparison:
Use case | Bash | PowerShell | Cmd |
---|---|---|---|
Create variable | variableName=varValue | $variableName="varValue" | set variableName=varValue |
Use variable as parameter value | variableName | $variableName | %variableName% |
Use variable in --query parameter |
'$variableName' | '$variableName' | '$variableName' |
There are several different ways to return variable information to your console screen, but echo
works in most circumstances. Here's a comparison:
- Bash: echo $varResourceGroup
- PowerShell: echo $varResourceGroup
- Cmd: echo %varResourceGroup%
In step three, Populate variables for use in scripts, you work through in-depth examples of variable syntax.
Learn about quoting differences between scripting languages
Every Azure CLI parameter is a string. However, each scripting language has its own rules for handling single and double quotes, spaces and parameter values.
String value | Azure CLI | PowerShell | Cmd |
---|---|---|---|
Text | 'text' or "text" | 'text' or "text" | "text" |
Number | \`50\` | ``50`` | `50` |
Boolean | \`true\` | ``false`` | 'true' |
Date | '2021-11-15' | '2021-11-15' | '2021-11-15' |
JSON | '{"key":"value"}' or "{"key":"value"}" | '{"key": "value"}' or "{`"key`": `"value`"}" or "{""key"": ""value""}" | "{"key":"value"}" |
Many Azure CLI parameters accept a space-separated list of values. This impacts quoting.
- Unquoted space-separated list: --parameterName firstValue secondValue
- Quoted space-separated list: --parameterName "firstValue" "secondValue"
- Values that contain a space: --parameterName "value1a value1b" "value2a value2b" "value3"
If you aren't sure how your string will be evaluated by your scripting language, return the value of a string to your console or use --debug
as explained in Debug Azure CLI reference commands.
Create a storage account to apply what you've learned
The remainder of this tutorial step demonstrates quoting rules in Azure CLI commands, and uses the resource group created in Prepare your environment for the Azure CLI. Substitute <msdocs-tutorial-rg-00000000>
with the name of your resource group.
Create an Azure storage account to use in this tutorial. This example assigns a random ID to the storage account name, but if you want to use a different name, see Storage account overview for storage account name rules.
Important
Before you can create a storage account, the Microsoft.Storage
resource provider must be registered in your subscription. To learn about registering resource types, see Register resource provider.
This next script example demonstrates scripting language-specific syntax for the following:
- Line continuation
- Variable usage
- Random identifiers
echo
command
# Variable block
let "randomIdentifier=$RANDOM*$RANDOM"
location="eastus"
resourceGroup="<msdocs-tutorial-rg-00000000>"
storageAccount="msdocssa$randomIdentifier"
# Create a storage account.
echo "Creating storage account $storageAccount in resource group $resourceGroup"
az storage account create --name $storageAccount \
--resource-group $resourceGroup \
--location $location \
--sku Standard_RAGRS \
--kind StorageV2 \
--output json
Note
Did you just receive a "Subscription not found" error? This error occurs when Microsoft.Storage
is not registered in the active subscription. To register a resource provider, see Azure resource providers and types.
The Azure CLI returns over 100 lines of JSON as output when a new storage account is created. The following JSON dictionary output has fields omitted for brevity.
{
"accessTier": "Hot",
"allowBlobPublicAccess": false,
"creationTime": "yyyy-mm-ddT19:14:26.962501+00:00",
"enableHttpsTrafficOnly": true,
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/ msdocs-tutorial-rg-00000000/providers/Microsoft.Storage/storageAccounts/msdocssa00000000",
"keyCreationTime": {
"key1": "yyyy-mm-ddT19:14:27.103127+00:00",
"key2": "yyyy-mm-ddT19:14:27.103127+00:00"
},
"kind": "StorageV2",
"location": "eastus",
"name": "msdocssa00000000",
"primaryEndpoints": {
"blob": "https://msdocssa00000000.blob.core.windows.net/"
},
"primaryLocation": "eastus",
"provisioningState": "Succeeded",
"resourceGroup": "msdocs-tutorial-rg-00000000",
"sku": {
"name": "Standard_RAGRS",
"tier": "Standard"
},
"statusOfPrimary": "available",
"statusOfSecondary": "available",
"tags": {},
"type": "Microsoft.Storage/storageAccounts"
}
Create tags to practice quoting differences
Using az storage account update, add tags to help you identify your storage account and learn about quoting differences. These script examples demonstrate scripting language-specific syntax for the following:
- Values containing spaces
- Quoting blank spaces
- Escaping special characters
- Using variables
The --tags
parameter accepts a space-separated list of key:value pairs. Substitute <msdocs-tutorial-rg-00000000>
with the name of your resource group and <msdocssa00000000>
with the name of your Azure storage account.
# Create new tags. This syntax works with or without quotes around each key-value pair.
az storage account update --name <msdocssa00000000> \
--resource-group <msdocs-tutorial-rg-00000000> \
--tags Team=t1 Environment=e1
# Create new tags containing spaces. You must use quotes.
az storage account update --name <msdocssa00000000> \
--resource-group <msdocs-tutorial-rg-00000000> \
--tags "Floor number=f1" "Cost center=cc1"
# Create a new tag with an empty value.
az storage account update --name <msdocssa00000000> \
--resource-group <msdocs-tutorial-rg-00000000> \
--tags "Department="''""
# Create a new tag containing special characters resulting in "Path": "$G:\\myPath".
az storage account update --name <msdocssa00000000> \
--resource-group <msdocs-tutorial-rg-00000000> \
--tags "Path=\$G:\myPath"
# Create a tag from a variable.
newTag="tag1=tag value with spaces"
az storage account update --name <msdocssa00000000> \
--resource-group <msdocs-tutorial-rg-00000000> \
--tags "$newTag"
If you don't want to overwrite previous tags while you work through this tutorial step, use the az tag update command setting the --operation
parameter to merge
.
# Get the resource ID of your storage account.
saID=$(az resource show --resource-group <msdocs-tutorial-rg-00000000> \
--name <msdocssa00000000> \
--resource-type Microsoft.Storage/storageAccounts \
--query "id" \
--output tsv)
echo My storage account ID is $saID
# Append new tags.
az tag update --resource-id $saID \
--operation merge \
--tags <tagName>=<tagValue>
# Get a list of all tags.
az tag list --resource-id $saID
Compare more scripting language-specific scripts
Take a deeper look at these script differences. These examples demonstrate quoting differences for the following:
- Pass a JSON string as a parameter value
- Filter results with the
--query
parameter- Numbers
- Boolean values
- Dates
Example of a parameter containing a JSON string. This script is given for future reference as we are not working with az rest
in this tutorial.
az rest --method patch \
--url https://management.azure.com/subscriptions/<mySubscriptionID>/resourceGroups/<myResourceGroup>/providers/Microsoft.HybridCompute/machines/<machineName>?api-version=yyyy-mm-dd-preview \
--resource https://management.azure.com/ \
--headers Content-Type=application/json \
--body '{"properties": {"agentUpgrade": {"enableAutomaticUpgrade": false}}}'
Example of filtering for a numeric value. Unless you have a VM in your current subscription, this example is given for future reference.
az vm list --resource-group <myResourceGroup> \
--query "[?storageProfile.osDisk.diskSizeGb >=\`50\`].{Name:name, admin:osProfile.adminUsername, DiskSize:storageProfile.osDisk.diskSizeGb}" \
--output table
Example of filtering a boolean value using the storage account created in this tutorial.
az storage account list --resource-group <msdocs-tutorial-rg-00000000> \
--query "[?allowBlobPublicAccess == \`true\`].id"
Examples of filtering a date using the storage account created in this tutorial.
# include time
az storage account list --resource-group <msdocs-tutorial-rg-00000000> \
--query "[?creationTime >='2021-11-15T19:14:27.103127+00:00'].{saName:name, saID: id, sku: sku.name}"
# exclude time
az storage account list --resource-group <msdocs-tutorial-rg-00000000> \
--query "[?creationTime >='2021-11-15'].{saName:name, saID: id, sku: sku.name}"
# subtract days and use a variable
saDate=$(date +%F -d "-30days")
az storage account list --resource-group <msdocs-tutorial-rg-00000000> \
--query "[?creationTime >='$saDate'].{saName:name, saID: id, sku: sku.name}"
Debug Azure CLI reference commands
Use --debug
parameter
The Azure CLI offers a --debug
parameter that can be used with any command. Debug output is extensive, but it gives you information including the following:
- Command arguments (parameter values) as interpreted by your scripting language
- Location of your log file
- API call detail
- Execution errors
If when working with Azure CLI commands you experience difficulty understanding and correcting an execution error, --debug
is your answer to see the steps Azure CLI is executing.
Here is a small portion of the debug output when creating a storage account:
cli.knack.cli: Command arguments: ['storage', 'account', 'create', '--name', 'msdocssa00000000', '--resource-group', 'msdocs-rg-test', '--location', 'eastus', '--sku', 'Standard_RAGRS', '--kind', 'StorageV2', '--output', 'json', '--debug']
...
cli.azure.cli.core.sdk.policies: Request URL: 'https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Storage/checkNameAvailability?api-version=2023-01-01'
cli.azure.cli.core.sdk.policies: Request method: 'POST'
cli.azure.cli.core.sdk.policies: Request headers:
cli.azure.cli.core.sdk.policies: 'Content-Type': 'application/json'
cli.azure.cli.core.sdk.policies: 'Content-Length': '73'
cli.azure.cli.core.sdk.policies: 'Accept': 'application/json'
cli.azure.cli.core.sdk.policies: 'x-ms-client-request-id': '00000000-0000-0000-0000-000000000000'
cli.azure.cli.core.sdk.policies: 'CommandName': 'storage account create'
cli.azure.cli.core.sdk.policies: 'ParameterSetName': '--name --resource-group --location --sku --kind --output --debug'
cli.azure.cli.core.sdk.policies: 'User-Agent': 'AZURECLI/2.61.0 (DEB) azsdk-python-core/1.28.0 Python/3.11.8 (Linux-5.15.153.1-microsoft-standard-WSL2-x86_64-with-glibc2.35)'
cli.azure.cli.core.sdk.policies: 'Authorization': '*****'
cli.azure.cli.core.sdk.policies: Request body:
cli.azure.cli.core.sdk.policies: {"name": "msdocssa00000000", "type": "Microsoft.Storage/storageAccounts"}
urllib3.connectionpool: Starting new HTTPS connection (1): management.azure.com:443
urllib3.connectionpool: https://management.azure.com:443 "POST /subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Storage/checkNameAvailability?api-version=2023-01-01 HTTP/1.1" 200 22
cli.azure.cli.core.sdk.policies: Response status: 200
...
For more troubleshooting tips, see Troubleshooting Azure CLI.
Use echo
command
Although --debug
tells you exactly what the Azure CLI is interpreting, a second option is to return the value of an expression to your console. This method is helpful when verifying the results of --query
that is covered in detail in Populate variables for use in scripts.
strExpression='{"key":"value"}'
echo $strExpression
{"key":"value"}
Troubleshooting
Here are common errors when an Azure CLI reference command syntax isn't written properly:
"Bad request ...{something} is invalid" might be caused by a space, single or double quotation mark, or lack of a quote.
"Unexpected token..." is seen when there's an extra space or quote.
"Invalid jmespath_type value" error often comes from incorrect quoting in the
--query
parameter."Variable reference is not valid" is received when a string isn't formatted properly often due to concatenation or a missing escape character.
"Unrecognized arguments" is often caused by an incorrect line continuation character.
"Missing expression after unary operator" is seen when a line continuation character is missing.
For additional troubleshooting tips, see Troubleshooting Azure CLI commands.
Get more details
Do you want more detail on one of the subjects covered in this tutorial step? Use the links in this table to learn more.
Subject | Learn more |
---|---|
Scripting differences | Quoting differences between scripting languages |
Bash quoting rules | |
PowerShell quoting rules | |
Considerations for running the Azure CLI in a PowerShell scripting language | |
Windows command-line tips | |
Parameters | Use quotation marks in Azure CLI parameters |
Find more syntax examples of Bash, PowerShell and Cmd in Query command output using JMESPath | |
Troubleshooting | Troubleshooting Azure CLI commands |
Next Step
Now that you learned how to write Azure CLI syntax for Bash, PowerShell and Cmd, proceed to the next step to learn how to extract values to a variable.