Month: April 2022

  • Using quotes in remote commands

    In my previous tutorial I showed how to escape quotes in Bash and PowerShell commands. So far so good. Now what if you want to execute a Bash command via SSH from a PowerShell instance?

    Let’s start with the plain Bash command we want to execute:

    echo $'Hello \' world!'

    This executed on Bash includes a single quote in the string. Please note the three single quotes in the command. Now to execute ssh on PowerShell on Windows we can use the following command:

    PS> ssh ago@server-0003 'YOUR_COMMAND_GOES_HERE'

    I spared the actual command in this line to show how this needs to “treated” in order to be executed remotely. Now we know from the previous tutorial that each single quote needs to be replaced with two single quotes in order to be recognized as string character and not as delimiting character. For the shown Bash command this would mean this:

    echo $''Hello \'' world!''

    Now we can replace “YOUR_COMMAND_GOES_HERE” with the treated command and this would be this:

    ssh ago@server-0003 'echo $''Hello\''world!'''
    Green: PowerShell, Red: Bash, Selected: Gets replaced with ‘ by PowerShell

    I hope this helps somebody.

  • Escaping in shells

    First things first: A string with spaces is enclosed in either single quotes ‘ or double quotes “. The difference you ask? Single quotes are treated “as is”: No variable replacement, no parsing, just a string. If you want to embed a variable value, you have to concatenate the string. Period. Double quotes allow dynamic values via variables:

    NAME="Andreas"
    echo "The name is $NAME"
    # Output: The name is Andreas

    This would print my name in the echo line.

    Okay, so now what if you need a quote in a echo line? Exactly, the same that is used to initiate and terminate the string? Well, you have to escape it. Let me make this clear: We are still working on a default Linux Bash now. Double quotes are relatively easy:

    echo "A string with a \" is fine."
    # Output: A string with a " is fine.

    Same goes for variables:

    NAME="Name with a \" character."
    echo "Value: $NAME"
    # Output: Value: Name with a " character.

    Single quotes are a little more tricky:

    echo $'String with a \' in it.'
    # Output: String with a ' in it.

    And as a variable:

    NAME=$'Name with a \' in it.'
    echo 'Value: '$NAME
    # Output: Value: Name with a ' in it.

    Okay, so now you can have quotes in strings that are framed by the same quotes. This is the beginning and I’d start practicing this for bash. I will continue this tutorial with PowerShell embedding:

    Write-Host "A string containing a `" character."
    # Output: A string containing a " character.

    As you can see, the escaping character is different from bash: PowerShell uses a ` to escape newline (`n) or quotes (`”).

    As we all know, MS is known for their consistency. Single quotes are treated differently:

    Write-Host 'A string containing a '' character.'
    # Output: A string containing a ' character.

    Isn’t that awesome?

    So why am I explaining this?

    Try to imagine the following scenario: You are working on a Windows-Machine (with PowerShell) and would like to run a command via SSH (basically a Linux tool) on a remote Linux server that runs BaSH. I’d suggest working from bottom (the command on the Linux server) to top (the command being written in the PowerShell environment). First execute it on Bash, then via SSH and finally embed it in the PowerShell command. This way you always know on which level you are and which escapes you are going to need.

    I will continue this tutorials because this always gave me a headache. Especially considering variables parsed on the executing host, the remote machine or coming from a command line. One has to work very concentrated here and always visualize where a certain part of a command is executed.

  • Check if remote database exists

    Escaping in PowerShell or in any other scripting language is not that much fun to begin with. So if you have quotes in quotes on different shells in different systems it becomes really funny. So trust me, I am more than surprised that I just found a neat way to check, if a database exists on a remote host with PowerShell (on Windows) and SSH (to a Linux machine):

    [string]::IsNullOrEmpty((ssh root@your.hostname.com 'mysql -N -e $''SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = \''databasename\'';'''))

    Execute this with a replaced host- and database name in PowerShell and it tells you “False” if your database exists or “True” if not because it is checked if the string is null or empty. Maybe just flip the boolean value in the end 🙂🙃

  • Unify line endings

    Let’s assume you have a software project and the line endings of the files are inconsistent. Meaning, that git commits and pushes without proper configuration will result in a merge disaster because the merge tools recognize the whole file as changed and not just the lines actually changed. When working on Windows or on a system that supports PowerShell you can use the following piece of code to change the line endings of all files in your project folder:

    Get-ChildItem -File -Recurse | ForEach-Object {
        try {
            $Content = Get-Content -Raw -Path $_.FullName
            $Content = $Content.Replace("`r`n", "`n")
            Set-Content -Path $_.FullName -Value $Content -NoNewline
        }
        catch {
            Write-Host -Object "Error handling file $($_.FullName)"
        }
    }

    This will load the content of each file, replace “\r\n” (Windows line endings) with “\n (Linux line endings) and write the content of the file into the same file it was read from.