none
foreach issue RRS feed

  • Question

  • When I try the "foreach" loop to try to copy the folder and all the contents to a USB drive, it works but it doesn't copy it structured, it copies it flat. No matter how I try it (I've included multiple examples), it copies to the destination flat...

    $ErrorActionPreference = 'Continue'
    $User = $env:USERNAME
    $FolderList = @(
    ($Home + '\' + "Desktop" + '\'),
    ($Home + '\' + "Documents" + '\'),
    ($Home + '\' + "Music" + '\') ,
    ($Home + '\' + "Pictures" + '\'),
    ($Home + '\' + "Videos" + '\'),
    ($Home + '\' + "Favorites" + '\'),
    ($Home + '\' + "Downloads" + '\'),
    ($Home + '\' + "AppData\Local\Google\Chrome\User Data\Default" + '\' + "Bookmarks")
    )

    $ExclusionList = @(
    "*.AVI",
    "*.AVS",
    "*.MOV",
    "*.MOVIE",
    "*.MOOV",
    "*.MPEG",
    "*.MPG",
    "*.QT",
    "*.QTM",
    "*.SCM",
    "*.M4V",
    "*.MP4",
    "*.WMV",
    "*.AA",
    "*.AIF",
    "*.AIFF",
    "*.IFO",
    "*.CDA",
    "*.MID",
    "*.MPE",
    "*.MUS",
    "*.MP1",
    "*.MP2",
    "*.MP3",
    "*.M4A",
    "*.M4P",
    "*.RA",
    "*.RAM",
    "*.WAV",
    "*.WMA",
    "*.TMP",
    "*.TEMP",
    "*.CHK",
    "*.MOZ",
    "*.SWP",
    "*.HFV",
    "*.HIB",
    '*.$$$',
    "*.ISO",
    "*.NRG",
    "*.NRI",
    "*.CIF",
    "*.GI",
    "*.lnk",
    "DataCopyLog.txt",
    "*.crdownload"
    )

    $USBdrive = gwmi win32_diskdrive | ?{$_.interfacetype -eq "USB"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} |  %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_.deviceid}

    foreach ($Folder in $FolderList) {Get-ChildItem -Path $Folder -Exclude $ExclusionList | % { Copy-Item $_.fullname -Destination ($USBdrive + $user) -Recurse -container -Force}}

    Additional information:

    If I run the commands individually on each folder, it copies it to the destination folder in a structured format:

    Get-ChildItem -Path $MyDocuments | % { Copy-Item $_.fullname ($USBdrive + $user + "\" + "Documents") -Recurse -container -Force -Exclude $ExclusionList }

    Not sure what I am doing wrong... 


    Jason Ostrowski



    • Edited by HomeTheaterGuy Thursday, August 2, 2018 2:01 PM
    • Moved by Bill_Stewart Wednesday, December 12, 2018 5:19 PM This is not "teach me basics step-by-step" forum
    Thursday, August 2, 2018 1:20 PM

All replies

  • Once again please post you code correctly using the code posting tool provided.

    \_(ツ)_/

    Thursday, August 2, 2018 1:26 PM
  • The system variable $home is NOT a string.  It is an object.  It will fail  as you are using it.

    The correct method is this:

    $FolderList = @(
        "$Home\Desktop\",
        "$Home\Documents\",
        "$Home\Music\" ,
        "$Home\Pictures\",
        "$Home\Videos\",
        "$Home\Favorites\",
        "$Home\Downloads\",
        "$Home\AppData\Local\Google\Chrome\User Data\Default\Bookmarks"
    )


    \_(ツ)_/

    Thursday, August 2, 2018 1:33 PM
  • $home does not necessarily point to the users folder. It point to the path set by Power Shell as the "script" directory or other places that may be set by GP.

    The correct way to get special folder locations is this:

     [environment]::GetFolderPath('Desktop')
     [environment]::GetFolderPath(Pictures)

    This is guaranteed even when the folders are redirected by Group Policy.


    \_(ツ)_/

    Thursday, August 2, 2018 1:36 PM
  • To get AppData\Local folders we would do this:

    "$env:LOCALAPPDATA\Google\Chrome\User Data\Default\Bookmarks"


    \_(ツ)_/

    Thursday, August 2, 2018 1:38 PM
  • Special folder names are per system and per user.  TO get the current folder names available use the following:

    [enum]::GetNames([System.Environment+SpecialFolder])


    \_(ツ)_/

    Thursday, August 2, 2018 1:40 PM
  • foreach ($Folder in $FolderList) {Write-Host $Folder}

    foreach ($Folder in $FolderList) {If(Test-Path $Folder) {Write-Host "Yes"}}
    foreach ($Folder in $FolderList) {Get-ChildItem -Path $Folder -Exclude $ExclusionList | Write-host}
    foreach ($Folder in $FolderList) {Get-ChildItem -Path $Folder -Recurse -Exclude $ExclusionList | Write-host}

    If I run the commands individually it copies it to the destination structured:

    Get-ChildItem -Path $MyDocuments | % { Copy-Item $_.fullname ($USBdrive + $user + "\" + "Documents") -Recurse -container -Force -Exclude $ExclusionList }

    Not sure what I am missing... 


    Jason Ostrowski

    What if you add the -Recurse parameter to the Get-ChildItem cmdlet?

    Get-ChildItem -Path $MyDocuments -Recurse | % { Copy-Item $_.fullname ($USBdrive + $user + "\" + "Documents") -Recurse -container -Force -Exclude $ExclusionList }

    Thursday, August 2, 2018 1:45 PM
  • Hi John

    When I run the command individually against each folder, it runs properly but if I put all the folders in a array then try the foreach, it copies to the destination flat (unstructured). 


    Jason Ostrowski

    Thursday, August 2, 2018 1:51 PM
  • Hi John

    When I run the command individually against each folder, it runs properly but if I put all the folders in a array then try the foreach, it copies to the destination flat (unstructured). 


    Jason Ostrowski

    Again.  Please go back and post your code correctly.  It is unreadable as posted.


    \_(ツ)_/

    Thursday, August 2, 2018 1:54 PM
  • Do I just edit the original?

    Jason Ostrowski

    Thursday, August 2, 2018 1:57 PM
  • Yes - just edit and cut and paste the code into the code tool.  You may want to clear up the indenting and make it as readable as you can.  We cannot debug your code if ew cannot read it easily.

    Also use my suggestions to fix the code and retest kt.


    \_(ツ)_/

    Thursday, August 2, 2018 1:59 PM
  • I changed all the lines with $home to:

    $FolderList = @(
    [environment]::GetFolderPath('Desktop'),
    [environment]::GetFolderPath('MyDocuments'),
    [environment]::GetFolderPath('MyMusic'),
    [environment]::GetFolderPath('MyPictures'),
    [environment]::GetFolderPath('MyVideos'),
    [environment]::GetFolderPath('Favorites'),
    #"$Env:USERPROFILE\Downloads",
    ([environment]::GetFolderPath('UserProfile') + 'Downloads'),
    "$env:LOCALAPPDATA\Google\Chrome\User Data\Default\Bookmarks"
    )

    Still copying to the destination folder unstructured... Yet, if I remove the "foreach" and then run the same command but adding the folder individually, then is copies properly (structured)... So I assume it's something with the syntax when using "foreach" that needs to be tweaked or added...


    Jason Ostrowski


    Thursday, August 2, 2018 2:12 PM
  • Please post your code using the code posting tool provided on the toolbar.  The code is still unreadable in most browsers.


    \_(ツ)_/

    Thursday, August 2, 2018 2:15 PM
  • Your last request is still too vague and without readable code we cannot even guess at your issue.


    \_(ツ)_/

    Thursday, August 2, 2018 2:16 PM
  • This is how to format and post code that is readable:

    $target = Join-Path $USBdrive $user
    foreach($folder in $folderList){
        Get-ChildItem -File -Path $folder -Exclude $exclusionList | 
            ForEach-Object{
                Copy-Item $_ -Destination $target -Verbose
            }
    }

    This loop will copy all files from the source folder to the target folder.


    \_(ツ)_/




    • Edited by jrv Thursday, August 2, 2018 2:23 PM
    Thursday, August 2, 2018 2:21 PM
  • I apologize for the misunderstanding, I thought you'd want the variables and arrays along with the code; in any future posts I will correct and follow that format!!!

    Jason Ostrowski

    Thursday, August 2, 2018 2:33 PM
  • This is how to format and post code that is readable:

    $target = Join-Path $USBdrive $user
    foreach($folder in $folderList){
        Get-ChildItem -File -Path $folder -Exclude $exclusionList | 
            ForEach-Object{
                Copy-Item $_ -Destination $target -Verbose
            }
    }

    This loop will copy all files from the source folder to the target folder.


    \_(ツ)_/

    This command didn't kick any errors but it also doesn't seem to do anything:

    $target = Join-Path $USBdrive $user

    foreach($folder in $folderList) { Get-ChildItem -File -Path $folder -Exclude $exclusionList | ForEach-Object {Copy-Item $_ -Destination $target -Verbose}}



    Jason Ostrowski

    Thursday, August 2, 2018 2:45 PM
  • When you are posting in a forum you are asking to collaborate with others.  It is a requirement for collaboration that code is styled and formatted so that others can read and understand your code.  Learning how to format and style code also helps you to see and understand your own code.

    In programming and scripting there are rules of style and display for code.  This debate was had 30 years ago and is still valid today.  Use style rules that are shared by all so all can understand your code.

    Here is a good place to start: PowerShell Style Guidelines


    \_(ツ)_/

    Thursday, August 2, 2018 2:47 PM
  • This command didn't kick any errors but it also doesn't seem to do anything:

    $target = Join-Path $USBdrive $user

    foreach($folder in $folderList) { Get-ChildItem -File -Path $folder -Exclude $exclusionList | ForEach-Object {Copy-Item $_ -Destination $target -Verbose}}



    Jason Ostrowski

    Please break your habit of putting everything on one line. It is unreadable and leads to errors. Code needs blank space to be readable.  What you see on the Internet where untrained people want to make everything a "one-liner" is bogus.  None of your code is a one-liner. It is just code crammed onto one line and is terribly annoying to anyone who knows how to write code.

    The code I posted will work assuming there are actually files in the source folder.  I suggest you test your folders by placing "write-host" statements in the code (which is very easy to do if you don't cram everything).

    $target = Join-Path $USBdrive $user
    Write-Host $target
    foreach($Folder in $FolderList){
        Get-ChildItem -File -Path $Folder -Exclude $ExclusionList | 
        ForEach-Object{
            Write-Host $_
            Copy-Item $_ -Destination $target -Verbose
        }
    }


    \_(ツ)_/

    Thursday, August 2, 2018 2:56 PM
  • Doesn't do anything but create a 148kb file with no extention in the root of the USB with my username BUT if I remove -file from  Get-ChildItem -File -Path it creates a folder with my username and copied everything FROM the folders into a sigle folder without the parent folder... So I don't get 7 folders with the contents contained to their original folder. Instead,  I get a single folder with the contents of all the folders listed in the $FolderList variable. So there is a secondary folder structure but not the parent folders from the source.... And that brings me back to where I started...

    Jason Ostrowski


    Thursday, August 2, 2018 3:16 PM
  • The "Destination" must be a folder that exists.

    I strongly recommend that you read the full help for all CmdLets you are trying to use.  We cannot guess at what you are doing or how you intend it to work.  Helping you is made very difficult by your lack of any experience with PowerShell.

    Start with:

    help Get-ChildItem -online
    help Copy-Item -online

    Look carefully at all parameter descriptions and all examples.  Try to understand what these CmdLets are designed to do and how they are designed to accomplish their tasks.


    \_(ツ)_/

    Thursday, August 2, 2018 3:28 PM
  • Something interesting...

    If I just run Copy-Item -Path $FolderList -Destination $target -Recurse -container -Force  -Exclude $exclusionList

    It works properly with 1 exception... It will only copy the contents of the very first folder in the list then copy the proceeding folders over properly structured... So, I moved an empty folder to the top of the list and the output was correct. But, if I didn't have that empty folder... I also get an access denied to each folder but it copies it anyway... 

    I will try to create the destination folder first then play with the variations to see if that corrects anything


    Jason Ostrowski

    Thursday, August 2, 2018 3:41 PM
  • By the way, I really appreciate everyone's help! I've only been doing powershell for about 3-4 months now and I value all the help and guidance that I get from you guys; it doesn't fall on someone who takes it for granted!

    Jason Ostrowski

    Thursday, August 2, 2018 3:52 PM
  • By the way, I really appreciate everyone's help! I've only been doing powershell for about 3-4 months now and I value all the help and guidance that I get from you guys; it doesn't fall on someone who takes it for granted!

    Jason Ostrowski

    Then it is time for you to stop guessing.  If you had done the following tutorial you wouldn't have been guessing for four months.

    Learn PowerShell

    DO th tutorial carefully.  The plus of a video is that you can pause it and try the code as it is presented.  Do all of the exercises and do not move to the next section until you are sure you understand the current lesson.  The instructors are PS experts.  Jeffery Snover is the "inventor" of PowerShell so you know you are getting correct info.  Many online videos and tutorial sites are not very good or are not accurate.  Many were done for PS1 or 2.  Current PowerShell is much different.

    The video is actually fun as the instructors really enjoy and understand PowerShell.


    \_(ツ)_/

    Thursday, August 2, 2018 4:01 PM
  • Something interesting...

    If I just run Copy-Item -Path $FolderList -Destination $target -Recurse -container -Force  -Exclude $exclusionList

    It works properly with 1 exception... It will only copy the contents of the very first folder in the list then copy the proceeding folders over properly structured... So, I moved an empty folder to the top of the list and the output was correct. But, if I didn't have that empty folder... I also get an access denied to each folder but it copies it anyway... 

    I will try to create the destination folder first then play with the variations to see if that corrects anything


    Jason Ostrowski

    So far it is mostly impossible to figure out what you are trying to do.

    Yes Get-ChildItem can take an array of folders.  What is the likelihood that one of the folders is protected?  You really need to learn basic PowerShell as we cannot incrementally debug your code as it has been posted.  You haven't even posted it correctly as I have asked you to do multiple time.


    \_(ツ)_/

    Thursday, August 2, 2018 4:34 PM
  • Something interesting...

    If I just run Copy-Item -Path $FolderList -Destination $target -Recurse -container -Force  -Exclude $exclusionList

    It works properly with 1 exception... It will only copy the contents of the very first folder in the list then copy the proceeding folders over properly structured... So, I moved an empty folder to the top of the list and the output was correct. But, if I didn't have that empty folder... I also get an access denied to each folder but it copies it anyway... 

    I will try to create the destination folder first then play with the variations to see if that corrects anything


    Jason Ostrowski

    So far it is mostly impossible to figure out what you are trying to do.

    Yes Get-ChildItem can take an array of folders.  What is the likelihood that one of the folders is protected?  You really need to learn basic PowerShell as we cannot incrementally debug your code as it has been posted.  You haven't even posted it correctly as I have asked you to do multiple time.


    \_(ツ)_/

    Hi jrv

    I was tasked with writing a script to migrate specific folders (My Documents, My Pictures, Desktop, etc...) for new PC migrations and they wanted to give the tech performing the transfer a choice to copy the folders to either a USB drive or Network folder; then it has to be restored to the same folder(s) on the new PC. My original script works without issue but I copied each folder individually, not using an array or  a loop of sorts. Then I wanted to add the "Write-Progress" feature so that you can see the % of the copy job running but was having an issue. So, I thought if I stream lined the script I would have better luck with the write-progress feature I want to add... That's where I am today..


    Jason Ostrowski

    Thursday, August 2, 2018 5:29 PM
  • Please fix you original post!!!  If we can't read it we can't help you.


    \_(ツ)_/

    Thursday, August 2, 2018 5:39 PM
  • Something interesting...

    If I just run Copy-Item -Path $FolderList -Destination $target -Recurse -container -Force  -Exclude $exclusionList

    It works properly with 1 exception... It will only copy the contents of the very first folder in the list then copy the proceeding folders over properly structured... So, I moved an empty folder to the top of the list and the output was correct. But, if I didn't have that empty folder... I also get an access denied to each folder but it copies it anyway... 

    I will try to create the destination folder first then play with the variations to see if that corrects anything


    Jason Ostrowski

    Hi Jason,

    The target directory needs to exist before you use Copy-Item.

    You can check if the target exists, and create the directory if not, before starting the Copy action.

    Also, you are probably getting the Access Denied errors on $env:username\documents\my pictures or music folders. That's because these are symbolic links and not the actual path. I believe it is safe to ignore these specific errors, as you have also included the physical path of the MyPictures, MyMusic, MyVideos folders.

    if (-not (Test-Path $target)) { 
        New-Item -Path $target -ItemType Directory 
    }
    Copy-Item -Path $FolderList -Destination $target -Recurse -container -Force -Exclude $exclusionList

    Best regards,

    John


    Thursday, August 2, 2018 6:16 PM
  • Hi Jason,

    Have you been able to find a solution?

    If your question has been answered in this thread, please don't forget to mark the thread as answered. It helps improve the chance of others with similar questions obtaining answers.

    Friday, August 17, 2018 12:13 PM