How to use bash's "| while read file do" and "done" in Powershell?

78 views Asked by At

What is bash's "| while read file do" and "done" in Powershell ?

For example, in bash the script is

cd tmp &&
inotifywait -me close_write,create,move --format %f *.tmp | while read file
do  rclone move "$file" dropbox:
done

What should it be like in Powershell?

I only found that && could be replaced with -and How about the rest?

1

There are 1 answers

2
mklement0 On

Use the ForEach-Object cmdlet, which processes each input object one by one.

With external programs, it is each output line that constitutes an object, i.e. PowerShell streams the (stdout) output from external programs line by line through its pipeline.

# See info re *.tmp and && below.
inotifywait -me close_write,create,move --format %f *.tmp | 
  ForEach-Object { rclone move $_ dropbox: }

Note:

  • In PowerShell, *.tmp only expands to the list of matching file names on Unix-like platforms, which requires use of PowerShell (Core) 7+, the modern, cross-platform edition of PowerShell.

    • On Windows (irrespective of whether you use PowerShell (Core) or the legacy Windows PowerShell edition), no such expansion is performed; replace *.tmp with (Get-Item *.tmp).Name there. (For more control over what gets matched, you can use Get-ChildItem instead of Get-Item).
      • Since this technique also works on Unix-like platforms, you can use it in cross-platform scripts.
  • The automatic $_ variable is used to refer to the input line at hand.

  • Enclosing variable references in "..." is not needed in PowerShell (in the case at hand, $_ is sufficient - no need for "$_"), even if the values contain spaces (PowerShell neither uses word-splitting nor most of the other shell expansions that Bash performs).

As for the cd tmp && ... part, i.e. use of &&:

  • You can use this syntax as-is in PowerShell (Core) 7+, which supports && and ||, the pipeline chain operators,

  • However, you can not in Windows PowerShell (and -and is not a substitute)[1]; there, use something like cd -ErrorAction Stop tmp (cd is a built-in alias of Set-Location) or cd tmp; if ($?) { ... }.


[1] See this answer for why.