Powershell: Move PowerShell folder on Windows from ${env:USERPROFILE}\OneDrive\Documents\PowerShell to ${env:USERPROFILE}\.powershell

Created on 18 Oct 2018  路  23Comments  路  Source: PowerShell/PowerShell

Recent releases of Windows 10 have replaced the Documents folder in a user's profile with OneDrive\Documents, which is automatically mirrored into each user's cloud-hosted OneDrive account. OneDrive only offers 5GB of cloud space for free, and once that is full important documents may not be mirrored into the cloud. Since Windows PowerShell modules can be quite large (the Az module bundle is 53MB, and the AWSPowerShell.NetCore module bundle is 81MB), it doesn't take much time with side-by-side versioning of frequently updated modules installed in a local user profile to start consuming a lot of OneDrive space, when there is no need to back those files up to OneDrive whatsoever since they are installed from a cloud repository.

To correct this, and provide one less reason for users' free OneDrive space to be completely and unnecessarily consumed, I propose that the Documents\PowerShell folder for PowerShell Core on Windows be moved and renamed to ${env:USERPROFILE}\.powershell. This new location and naming is in line with other products like Nuget (uses a .nuget folder for package storage), VS Code (uses .vscode), LibMan in Visual Studio (uses .librarymanager), and many more. This shift is the right approach based on new handling and best practices for a user's Documents folder in Windows, which should only be used to store documents that users want automatically backed up into the cloud.

Committee-Reviewed Issue-Discussion Resolution-Answered

Most helpful comment

I agree with the OP on this issue. I recently upgraded my Win10 and now I got those files in Onedrive/Documents as well. While I like the idea of sharing my default profiles and possibly scripts across PCs using OneDrive, this should be done using the proper Windows folders, namely AppData Local/Roaming, because this is the convention on Windows and it works well. Also better than dotfiles and dotfolders in the home directory.

So the correct path would be something like $env:APPDATA\Microsoft\Powershell\ or $env:LOCALAPPDATA\Microsoft\Powershell\

All 23 comments

It should use the XDG Base Directory Specification like the other operating system. Is there any reason to have Windows be different?

@thezim I don't agree or disagree (I wasn't familiar with that spec before you mentioned it), but at a glance I think that is a different issue to propose than this specific problem that should be resolved independently of a directory specification.

Sorry for not being clear. What I meant to say was PowerShell already respects XDG spec for Linux and macOS. We should extend that to Windows as well. Module when then go in ~/.local/share/powershell/Modules which would address the issue.

https://github.com/PowerShell/PowerShell-Docs/blob/staging/reference/docs-conceptual/setup/Installing-PowerShell-Core-on-Linux.md#paths

https://github.com/PowerShell/PowerShell-Docs/blob/staging/reference/docs-conceptual/setup/Installing-PowerShell-Core-on-macOS.md#paths

I've never liked modules being stored under Documents. Seems to me they should have been stored under $env:\LocalAppData\Microsoft\PowerShell\Modules or some path like that.

BTW I defined this symlink a while back in my home dir:

.powershell -> C:\Users\Keith\Documents\WindowsPowerShell\

I wonder if .dirs should be hidden by default like they are on Linux? I suppose mostly developers will wind up with these so perhaps it's OK that they're not hidden.

RE ~\.local, I like the idea but you've got some other teams to convince:

.config
.dotnet
.electron
.nuget
.omnisharp
.rcedit
.vscode
.vscode-insiders

I don鈥檛 perfer .local either but having it the same across all platforms would be nice for PowerShell. All those teams are consistent across their platforms, we are not.

I agree with the benefits of consistency. The path doesn't matter so much since you can just set up PSDrive's in a profile, and I wasn't personally attached to the path I proposed -- I simply chose it based on the other similar paths like .nuget, .vscode, etc.

I discovered this ~/OneDrive "feature" the other day login into a new machine. It has to be moved, because you will lose the ability to have unique profiles local to a particular machine. Not to mention scripts are not Documents in the first place.

I find it handy to have Powershell modules/profile roam using Onedrive. That said, I agree consistency with the other OS'es would be better. I usually run a powershell setup script manually on each machine I use to symlink the profiles back to onedrive anyway.

I agree with the OP on this issue. I recently upgraded my Win10 and now I got those files in Onedrive/Documents as well. While I like the idea of sharing my default profiles and possibly scripts across PCs using OneDrive, this should be done using the proper Windows folders, namely AppData Local/Roaming, because this is the convention on Windows and it works well. Also better than dotfiles and dotfolders in the home directory.

So the correct path would be something like $env:APPDATA\Microsoft\Powershell\ or $env:LOCALAPPDATA\Microsoft\Powershell\

Is it possible to change it manually? And if so how I can do it?

@SteveL-MSFT It would be nice to iron out the direction on this one for PS 7, to bring Windows PS and PS Core together with a better user module/script path on Windows. Would you mind tabling this with the committee?

Thanks for raising this! I wasn't aware of these latest changes to the Documents folder, but I'd like to have some more internal discussion before we make a call either way. In particular, I'm concerned about the difficulty of creating and managing symlinks downlevel (where they're essentially only manageable by administrators).

Thanks for raising this! I wasn't aware of these latest changes to the Documents folder, but I'd like to have some more internal discussion before we make a call either way. In particular, I'm concerned about the difficulty of creating and managing symlinks downlevel (where they're essentially only manageable by administrators).

Why use the documents folder in the first place? Powershell profiles / scripts / modules are not documents in the traditional meaning. I suggest use the generic appfolders (local, roaming) provided in Windows by default instead of using Documents or even the proposed $env:USERPROFILE.powershell. While the latter is common on *nix operating systems, the appfolders are the way to go on Windows.

Please don't bury them all the way in appdata. There's far too much stuff in there to go trying to find PowerShell profiles. Somewhere in $home is fine.

@totkeks Better for a consistent location across OSes than one location in Windows and a different one for macOS/Linux IMHO.

It would be nice if we had the ability to override the location via an environment variable if needed.

@PowerShell/powershell-committee reviewed this, and we believe the risk of changing the "user PowerShell folder" across versions/editions of PowerShell and downlevel versions of the OS is too high to take the chance. Symlinks aren't well supported downlevel, and if users want to change their Documents to not use OneDrive, they can do so. Additionally, migration logic on upgrades (and/or moving/linking to existing folders) is extremely hard to get right 100%, and we don't want to leave users in a broken state. Additionally, $profile can be used for changing PSModulePath or executing profiles in other locations, and users can create their own symlinks for re-routing the folder.

That being said, it might be worth creating an automatic variable in PowerShell that points to the "user PowerShell folder" across platforms.

Wouldn't an environment variable be better than an automatic variable, so that it could be set broadly across many systems? Then PowerShell could check for the presence of that environment variable on launch, and if present, use that path as the user profile path, otherwise, use the default path as the user profile path.

Another argument for an environment variable is for profiles. Today user profiles are loaded from the user profile path. That wouldn't work with an automatic variable that you update as part of your user profile.

@KirkMunro technically what you describe is only accurate in 4 particular scenarios and in each of these this is historically kept in line with existing on Windows functionality where User PSModulePath has always been housed in $env:userprofile\Documents

  1. You log in with a Microsoft account to a new Device - this is something you can bypass completely and use a Local Only account mitigating this issue completely
  2. You log into a new device that has Organisational policies that enforces the use of Onedrive for Business
  3. You sign into OneDrive (consumer) on a device using a non-Microsoft account, ie a local login, and link it with your Microsoft account login
  4. You sign into OneDrive for Business on a device using a either an AD or AAD backed account and link it with your organisations Office 365 instance.

In Scenario 1/3
Creating a new Local user and using that bypasses this being an issue
Also telling OneDrive not to sync the PowerShell Folder (which you can do in the UI nice and easily) again bypasses this being a problem from size concerns but adds another one where syncing your profile script and other needed scripts is now a manual task.

In Scenario 2/4
The User $PSModulePath updates to either

  • $env:userprofile/Onedrive-<Orgname>/Documents
  • $env:userprofile/Onedrive/Documents

because under the Hood OneDrive Sync Client has performed User Document folder redirection which is actually set as a registry setting which is all that is being read here to create the path used in PowerShell

If you never enable Onedrive sync of the docs folder then the folder stays $env:userprofile/Documents/

The only time I know this to be different is when orgs set Users Home Drives to be a H Drive on a mapped drive location which is often set in AD and enforced via GPO which is also just a reg key setting. But that just updates the $env:userprofile variable not the docs folder itself

So technically this is NOT a PowerShell issue to contemplate solving and is something that with user training to say hey you can tell Onedrive not to sync that PowerShell Folder but still sync everything else in the Docs folder

Why use the documents folder in the first place? Powershell profiles / scripts / modules are not documents in the traditional meaning. I suggest use the generic appfolders (local, roaming) provided in Windows by default instead of using Documents or even the proposed $env:USERPROFILE.powershell. While the latter is common on *nix operating systems, the appfolders are the way to go on Windows.

Scripts are still documents, whether they are traditional documents or not is neither here nor there, same with any text file and as such should be loosely treated like standard document

I for one can't stand the messiness caused by all the apps that write configurations to a folder like below because they do not allow me to bring my configurations of those applications across with me as a user of those applications to new machines. where as in the docs folder I can dump 100 scripts that I may need inc my profile script and 20 modules that I need and be 100% sure that I can rebuild that machine or deploy an additional machine and my profile brings these modules and scripts with me ready to use straight away, lowering the mean time to recover if i suffer a bricked update or a hardware failure or even a lost/stolen device.
image

Overall this is a 10+ year profile placement that at the time made sense for admin scripters and IMO still makes sense in its current implementation - I am aware I am in the minority in this thread but IMO changing this to a .powershell folder in $env:userprofile or $env:LocalAPPDATA $env:APPDATA to me feels like a mix of breaking existing well understood functionality and wasted engineering effort for what I see to be no actual useful gain.

and to @joeyaiello point I can't see a need for adding engineering effort behind an automatic var that perhaps is going to be used by a very small subset of users compared to the mass majority

@kilasuit Why all the soapboxing for a issue that the Committee already responded to? Per their response, the default location of the user profile for PowerShell isn't going to change.

As for engineering effort on an environment variable, this is open source. I wasn't asking the PS Team to do it, nor would I expect them to. I'll do it via a PR though, because it matters to myself, and others as well.

If this one becomes a greater issue in the future, feel free to re-file, but given the decision, I'm going to close it.

I'm aware this is a closed issue, but I found this discussion after running into the same issue as @KirkMunro (problems syncing Onedrive\Docuements\WindowsPowerShell), and wanted to post my solution for posterity.

Ultimately, what I did was to leave WindowsPowerShell in its default location, but to add the following code to my profile.ps1 file:
$env:PSModulePath = $env:PSModulePath -replace "\\OneDrive\\Documents\\WindowsPowerShell\\","\.powershell\"

This leaves the WindowsPowerShell folder in its default location, but allows the modules to be saved in $env:USERPROFILE.powershell, which does not sync to onedrive.

But it does not change the location for local help, does it?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

andschwa picture andschwa  路  3Comments

HumanEquivalentUnit picture HumanEquivalentUnit  路  3Comments

alx9r picture alx9r  路  3Comments

rudolfvesely picture rudolfvesely  路  3Comments

garegin16 picture garegin16  路  3Comments