1

I have a text file which a list of JSON files.

Using Powershell, I am able to extract these out of the file and then print the filenames out.

However I want to write a command then execute that in a foreach loop, but the concatenation is proving tricky.

This is my code so far:

foreach($line in [System.IO.File]::ReadLines("C:\Temp\DbAdmin\ImportDERReturn\ImportDERReturn.txt"))
{
  Write-Host 'aws s3 rm  s3://Derwent-storage-internal/staging/returns/' + $line.Substring(0,16) + '  --profile DER'
}

However im getting the following output:

aws s3 rm s3://Derwent-storage-internal/staging/returns/ + RET02022203.json +   --profile DER

But what I want is the following:

aws s3 rm  s3://Derwent-storage-internal/staging/returns/RET02022203.json --profile DER

How do I get this output? How do I get my Powershell script to execute this line?

Paolo
  • 21,270
  • 6
  • 38
  • 69
ChrisAsi71
  • 41
  • 4

1 Answers1

1
  • Don't use Write-Host to output data; it is meant for to-display output, and bypasses PowerShell's success output stream (see this answer for more information).

  • To output data, you don't need an explicit output command at all, so the following by itself is enough:

    'aws s3 rm s3://Derwent-storage-internal/staging/returns/' + $line.Substring(0,16) + ' --profile DER'
    
    • If you do want to use an explicit output command to emit data (which is rarely necessary), use Write-Output or its built-in alias, echo; in that case you need to enclose your string-concatenation expression (using the + operator), in (...), the grouping operator:

      # Note the use of (...) around the concatenation expression.
      echo ('aws s3 rm s3://Derwent-storage-internal/staging/returns/' + $line.Substring(0,16) + ' --profile DER')
      
  • As for executing your lines: just invoke aws directly and use either the (...) technique or, more simply string interpolation via a expandable (double-quoted) string ("...") (line breaks with ` for line continuations are purely for readability):

    aws s3 rm `
     "s3://Derwent-storage-internal/staging/returns/$($line.Substring(0,16))" `
     --profile DER
    
    • If you first want to echo the command, use a script block (note that here ` is used to escape the embedded " inside "..."):

      $sb = [scriptblock]::Create("s3 rm `"s3://Derwent-storage-internal/staging/returns/$($line.Substring(0,16))`" --profile DER")
      # Echo
      $sb.ToString()
      # Execute, using &, the call operator.
      & $sb
      
    • Invoke-Expression (whose built-in alias is iex), offers a slightly simpler alternative, though note that Invoke-Expression should generally be avoided, due to potential security risks:

       $str = "s3 rm `"s3://Derwent-storage-internal/staging/returns/$($line.Substring(0,16))`" --profile DER"
       # Echo
       $str
       # Execute, using iex (Invoke-Expression)
       iex $str
      
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Hi guys thanks for your help on this. So we are deleting files from AWS s3 bucket. they have all been processed and checked through our system so we are good to clear them down...and yes i trust the input from the file...so i will run with iex to invoke expression thanks for your help and have a great weekend! – ChrisAsi71 Aug 11 '23 at 16:05
  • Glad to hear it helped, @ChrisAsi71. Note that while you _can_ use `iex` (`Invoke-Expression`), as shown in an earlier revision of this answer, there are better alternatives, as now shown in the answer. Note that you can help future readers by clearly signaling which answer, if any, solved your problem, namely by [accepting](https://meta.stackexchange.com/a/5235/248777) it. Have a great weekend, too. – mklement0 Aug 11 '23 at 16:08
  • On second thought, @ChrisAsi71: Since the script-block approach offers no security benefit over `Invoke-Expression` here, I've added an `Invoke-Expression` solution back to the answer. – mklement0 Aug 11 '23 at 16:15