Powershell: Out-File should create missing parent folders

Created on 31 Aug 2020  ·  13Comments  ·  Source: PowerShell/PowerShell

Summary of the new feature/enhancement


It would be nice for Out-File to create missing parent folders. Possibly require the -Force flag for this to take effect.

Currently to safely output to a file in a different folder, it's safest to preface your command with a New-Item -Force command.

Proposed technical implementation details (optional)

Area-Cmdlets-Utility Issue-Question Resolution-Answered

All 13 comments

Adding more detail. To me this is what I would expect to happen with the -Force flag. This could possible be classified as a bug, although I labeled it as an enhancement to be safe.

Current Behavior

❯ tree
+ C:\temp
❯ 'example error' | Out-File 'logs/error-log.txt' -Force
Out-File: Could not find a part of the path 'C:\temp\logs\error-log.txt'.

Desired Behavior

❯ tree
+ C:\temp
❯ 'example error' | Out-File 'logs/error-log.txt' -Force
❯ tree
+ C:\temp
  + logs
    - error-log.txt
❯ cat .\logs\error-log.txt
example error

While desired-state functionality is a wonderful thing, the problem is that (a) users have come to expect -Force to have a specific meaning with respect to Out-File (to override a read-only attribute on Windows) and (b) to overload a single flag with multiple, unrelated behaviors is problematic.

It's not as concise, but you can use New-Item's -Force flag:

```powershell
'foo' | Out-File "$(New-Item -Force -Type Directory logs)/error-log.txt"
````

I can understand where overloading the functionality of the Force flag could be problematic. I propose adding a new flag to achieve this functionality. While the statement you provided above works, it hurts readability. I feel like it's reasonable for the end user to expect that Out-File has the ability to create the file (and parent directories) that it's trying to write to. I also feel like this would desired functionality by end users. Of course this is just my opinion, but if others agree, I think this would be a valuable feature to add.

Understood, but at this point I suggest you close _this_ issue, and create a new one, using the "Feature Request/Idea" template, in which you can:

  • present the proposal along with suggesting a specific (switch) parameter name.

  • also consider how and which _additional_ file-creating cmdlets - notably Set-Content, which is the faster choice if the input objects already are strings - could be covered.

This thread was created by selecting Feature Request/Idea. My initial comment recommended the Force flag since it matches the functionality of New-Item. I'm not familiar enough with this repository to feel comfortable recommending anything more specific than the desire for Out-File to be capable of generating parent folders. I'm open to suggestions, and I'd happily create a new topic to propose that.

Sorry - I missed that you had indeed used the right template - it was @iSazonov who removed the Issue-Enhancement label and replaced with Issue-Question (which is the default for the _bug_ template).

My sense was that the -Force aspect of your suggestion - which I think we now agree was a dead end - created a _distraction_, so I proposed creating a new "Feature Request/Idea" post - which I still recommend: you can simply _mention_ the aspect of perhaps needing to cover additional cmdlets, soliciting input from others.

Ok, thank you, I will try that. Do you have any suggestion what the flag should be named? I'm not aware or anything with similar functionality to take cues from.

@Joe-Zer0, good question re name for the switch (flag) - I don't think there is a precedent (except in New-Item -Type Directory, where the already ruled-out -Force serves that purpose) and I can't think of anything that strikes the right balance between concision and descriptiveness - something like -CreateDirectoryOnDemand feels clunky.

Perhaps that's an indication that the functionality doesn't really belong there, which is my personal sense.

But I don't want to discourage you from creating a proposal - feel free to create it and see what others say.

-Force isn't required for New-Item -Type Directory (though it is if you're doing -Type File and targeting a file path that contains nonexistent directories).

But yeah, personally I'm kind of feeling this doesn't belong in Out-File itself.

@vexx32, -Force _is_ required if you want _desired-state_ functionality, which is what this issue is about.

That is, if you want New-Item -Type Directory to either create the target directory _on demand_ (and return information about it) or return information about an _existing_ target directory at the specified path, -Force is required.

However, you bring up a good point: with New-Item -Type File (-Type File being the default), creating the parent directory on demand _does_ work; thus, @Joe-Zer0's command could have been rewritten as:

# Replace any existing logs/error-log.txt file
#  *or* 
# create the /logs/ subdir. on demand an create the 'error-log.txt' file in it.
New-Item -Force 'logs/error-log.txt' -Value 'example error'

I was previously using "if Test-Path" prior to my output redirection. Since this doesn't seem to be getting much traction, I decided to adapt some sample code that @mklement0 posted. It's a bit cleaner that having extra if statements. I also switched back to the redirection operator since I had no use for any Out-File flags.

random command > $(New-Item logs/error-log.txt -Force)

This is a fairly clean method of redirecting output while ensuring the destination file exist. Thanks for both of your help and feedback!

@Joe-Zer0, that's a nice idiom, thanks for sharing.

You can even make it (ever so slightly) shorter by using (...) rather than $(...).
In case you're curious about the difference and when to use which, see this SO answer.

@mklement0
Thanks for that SO link. I've recently been realizing I've been using $() more than I should. That helps me with understanding when it's actually necessary.

Was this page helpful?
0 / 5 - 0 ratings