PowerShell script not zipping correct files












2















 Function Zip
{
Param
(
[string]$zipFile
,
[string]$toBeZipped
)
$CurDir = Get-Location
Set-Location "C:Program Files7-Zip"
.7z.exe A -tzip $zipFile $toBeZipped | Out-Null
Set-Location $CurDir
}
$Now = Get-Date
$Days = "60"
$TargetFolder = "C:usersAdminDownloads*.*"
$LastWrite = $Now.AddDays(-$Days)
$Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}
$Files
Zip C:UsersAdminDesktopTEST.zip $Files


I am testing out this script I found online. My problem is that instead of zipping the files in the target folder, it is copying and zipping the contents of the 7-zip program file folder. What could cause this? Thanks in advance










share|improve this question

























  • Where did you find the script? When file objects are forced to strings they just become the file names... not the full path. I think you need to process each file 1 by 1. Also you could remove Out-Null to help get yourself more information as to what is happening.

    – Matt
    Nov 20 '18 at 19:18













  • @Matt: Here they indeed stringify to file names only, which is the problem, but whether they stringify to mere file names or full paths generally depends on the specifics of the Get-ChildItem call, (very) unfortunately - I've tried to summarize the rules in my answer.

    – mklement0
    Nov 20 '18 at 20:33











  • I saw that. Colour me impressed. It annoys me that it is inconsistent. I'm just used to using fullnames now

    – Matt
    Nov 20 '18 at 20:35






  • 1





    @Matt: Yes, it's very unfortunate behavior that makes for insidious bugs. I'm glad the problem no longer occurs in PS Core (and let's hope that the change, which was technically a breaking one, was intentional or will at least be retained).

    – mklement0
    Nov 20 '18 at 20:38
















2















 Function Zip
{
Param
(
[string]$zipFile
,
[string]$toBeZipped
)
$CurDir = Get-Location
Set-Location "C:Program Files7-Zip"
.7z.exe A -tzip $zipFile $toBeZipped | Out-Null
Set-Location $CurDir
}
$Now = Get-Date
$Days = "60"
$TargetFolder = "C:usersAdminDownloads*.*"
$LastWrite = $Now.AddDays(-$Days)
$Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}
$Files
Zip C:UsersAdminDesktopTEST.zip $Files


I am testing out this script I found online. My problem is that instead of zipping the files in the target folder, it is copying and zipping the contents of the 7-zip program file folder. What could cause this? Thanks in advance










share|improve this question

























  • Where did you find the script? When file objects are forced to strings they just become the file names... not the full path. I think you need to process each file 1 by 1. Also you could remove Out-Null to help get yourself more information as to what is happening.

    – Matt
    Nov 20 '18 at 19:18













  • @Matt: Here they indeed stringify to file names only, which is the problem, but whether they stringify to mere file names or full paths generally depends on the specifics of the Get-ChildItem call, (very) unfortunately - I've tried to summarize the rules in my answer.

    – mklement0
    Nov 20 '18 at 20:33











  • I saw that. Colour me impressed. It annoys me that it is inconsistent. I'm just used to using fullnames now

    – Matt
    Nov 20 '18 at 20:35






  • 1





    @Matt: Yes, it's very unfortunate behavior that makes for insidious bugs. I'm glad the problem no longer occurs in PS Core (and let's hope that the change, which was technically a breaking one, was intentional or will at least be retained).

    – mklement0
    Nov 20 '18 at 20:38














2












2








2


3






 Function Zip
{
Param
(
[string]$zipFile
,
[string]$toBeZipped
)
$CurDir = Get-Location
Set-Location "C:Program Files7-Zip"
.7z.exe A -tzip $zipFile $toBeZipped | Out-Null
Set-Location $CurDir
}
$Now = Get-Date
$Days = "60"
$TargetFolder = "C:usersAdminDownloads*.*"
$LastWrite = $Now.AddDays(-$Days)
$Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}
$Files
Zip C:UsersAdminDesktopTEST.zip $Files


I am testing out this script I found online. My problem is that instead of zipping the files in the target folder, it is copying and zipping the contents of the 7-zip program file folder. What could cause this? Thanks in advance










share|improve this question
















 Function Zip
{
Param
(
[string]$zipFile
,
[string]$toBeZipped
)
$CurDir = Get-Location
Set-Location "C:Program Files7-Zip"
.7z.exe A -tzip $zipFile $toBeZipped | Out-Null
Set-Location $CurDir
}
$Now = Get-Date
$Days = "60"
$TargetFolder = "C:usersAdminDownloads*.*"
$LastWrite = $Now.AddDays(-$Days)
$Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}
$Files
Zip C:UsersAdminDesktopTEST.zip $Files


I am testing out this script I found online. My problem is that instead of zipping the files in the target folder, it is copying and zipping the contents of the 7-zip program file folder. What could cause this? Thanks in advance







powershell scripting zip target 7zip






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 '18 at 21:33









mklement0

132k21246284




132k21246284










asked Nov 20 '18 at 18:40









techguy1029techguy1029

6711




6711













  • Where did you find the script? When file objects are forced to strings they just become the file names... not the full path. I think you need to process each file 1 by 1. Also you could remove Out-Null to help get yourself more information as to what is happening.

    – Matt
    Nov 20 '18 at 19:18













  • @Matt: Here they indeed stringify to file names only, which is the problem, but whether they stringify to mere file names or full paths generally depends on the specifics of the Get-ChildItem call, (very) unfortunately - I've tried to summarize the rules in my answer.

    – mklement0
    Nov 20 '18 at 20:33











  • I saw that. Colour me impressed. It annoys me that it is inconsistent. I'm just used to using fullnames now

    – Matt
    Nov 20 '18 at 20:35






  • 1





    @Matt: Yes, it's very unfortunate behavior that makes for insidious bugs. I'm glad the problem no longer occurs in PS Core (and let's hope that the change, which was technically a breaking one, was intentional or will at least be retained).

    – mklement0
    Nov 20 '18 at 20:38



















  • Where did you find the script? When file objects are forced to strings they just become the file names... not the full path. I think you need to process each file 1 by 1. Also you could remove Out-Null to help get yourself more information as to what is happening.

    – Matt
    Nov 20 '18 at 19:18













  • @Matt: Here they indeed stringify to file names only, which is the problem, but whether they stringify to mere file names or full paths generally depends on the specifics of the Get-ChildItem call, (very) unfortunately - I've tried to summarize the rules in my answer.

    – mklement0
    Nov 20 '18 at 20:33











  • I saw that. Colour me impressed. It annoys me that it is inconsistent. I'm just used to using fullnames now

    – Matt
    Nov 20 '18 at 20:35






  • 1





    @Matt: Yes, it's very unfortunate behavior that makes for insidious bugs. I'm glad the problem no longer occurs in PS Core (and let's hope that the change, which was technically a breaking one, was intentional or will at least be retained).

    – mklement0
    Nov 20 '18 at 20:38

















Where did you find the script? When file objects are forced to strings they just become the file names... not the full path. I think you need to process each file 1 by 1. Also you could remove Out-Null to help get yourself more information as to what is happening.

– Matt
Nov 20 '18 at 19:18







Where did you find the script? When file objects are forced to strings they just become the file names... not the full path. I think you need to process each file 1 by 1. Also you could remove Out-Null to help get yourself more information as to what is happening.

– Matt
Nov 20 '18 at 19:18















@Matt: Here they indeed stringify to file names only, which is the problem, but whether they stringify to mere file names or full paths generally depends on the specifics of the Get-ChildItem call, (very) unfortunately - I've tried to summarize the rules in my answer.

– mklement0
Nov 20 '18 at 20:33





@Matt: Here they indeed stringify to file names only, which is the problem, but whether they stringify to mere file names or full paths generally depends on the specifics of the Get-ChildItem call, (very) unfortunately - I've tried to summarize the rules in my answer.

– mklement0
Nov 20 '18 at 20:33













I saw that. Colour me impressed. It annoys me that it is inconsistent. I'm just used to using fullnames now

– Matt
Nov 20 '18 at 20:35





I saw that. Colour me impressed. It annoys me that it is inconsistent. I'm just used to using fullnames now

– Matt
Nov 20 '18 at 20:35




1




1





@Matt: Yes, it's very unfortunate behavior that makes for insidious bugs. I'm glad the problem no longer occurs in PS Core (and let's hope that the change, which was technically a breaking one, was intentional or will at least be retained).

– mklement0
Nov 20 '18 at 20:38





@Matt: Yes, it's very unfortunate behavior that makes for insidious bugs. I'm glad the problem no longer occurs in PS Core (and let's hope that the change, which was technically a breaking one, was intentional or will at least be retained).

– mklement0
Nov 20 '18 at 20:38












2 Answers
2






active

oldest

votes


















3














Pass the files as full paths to the Zip function, using their .FullName property (PSv3+ syntax):



Zip C:UsersAdminDesktopTEST.zip $Files.FullName




The problem is that the [System.IO.FileInfo] instances returned by Get-ChildItem situationally[1] stringify to their file names only, which is what happened in your case, so your Zip function then interpreted the $toBeZipped values as relative to the current location, which is C:Program Files7-Zip at that point.



That said, it's better not to use Set-Location in your function altogether, so that in the event that you do want to pass actual relative paths, they are correctly interpreted as relative to the current location:



Function Zip {
Param
(
[Parameter(Mandatory)] # make sure a value is passed
[string]$zipFile
,
[Parameter(Mandatory)] # make sure a value is passed
[string]$toBeZipped
)
# Don't change the location, use & to invoke 7z by its full path.
$null = & "C:Program Files7-Zip7z.exe" A -tzip $zipFile $toBeZipped
# You may want to add error handling here.
}




[1] When Get-ChildItem output stringifies to file names only:



Note:





  • Get-Item output always stringifies to the full path, fortunately.


  • In PowerShell Core, Get-ChildItem too always stringifies to the full path, which is commendable, but it's unclear whether the change was intentional.


The following therefore only applies to Get-ChildItem in Windows PowerShell:



The problem is twofold:




  • Even PowerShell's built-in cmdlets bind file / directory arguments (parameter values - as opposed to input via the pipeline) not as objects, but as strings (changing this behavior is being discussed in this GitHub issue).


  • Therefore, for robust argument-passing, you need to ensure that your Get-ChildItem output consistently stringifies to full paths, which Get-ChildItem does not guarantee - and it's easy to forget when name-only stringification occurs of even that you need to pay attention to it at all.



Always passing the .FullName property values instead is the simplest workaround or, for reliable operation with any PowerShell provider, not just the filesystem, .PSPath.



[System.IO.FileInfo] and [System.IO.DirectoryInfo] instances output by a Get-ChildItem command stringify to their file names only, if and only if:




  • If one or more literal directory paths are passed to -LiteralPath or -Path (possibly as the 1st positional argument) or no path at all is passed (target the current location); that is, if the contents of directories are enumerated.


  • and does not also use the -Include / -Exclude parameters (whether -Filter is used makes no difference).



  • By contrast, whether or not the following are also present makes no difference:





    • -Filter (optionally as the 2nd positional argument, but note that specifying a wildcard expression such as *.txt as the 1st (and possibly only) positional argument binds to the -Path parameter)


    • -Recurse (by itself, but note that it is often combined with -Include / -Exclude)




Example commands:



# NAME-ONLY stringification:

Get-ChildItem | % ToString # no target path

Get-ChildItem . | % ToString # path is literal dir.

Get-ChildItem . *.txt | % ToString # path is literal dir., combined with -Filter

# FULL PATH stringification:

Get-ChildItem foo* | % ToString # non-literal path (wildcard)

Get-ChildItem -Recurse -Include *.txt | % ToString # use of -Include

Get-ChildItem file.txt | % ToString # *file* path





share|improve this answer

































    1














    If you (temporarily) disable the |Out-Null you'll see what error msg pass along.

    $Files contains objects not just an array of file names.



    By default powershell tries to stringify this using the Name property which doesn't contain the path - so 7zip can't find the files as you also change the path to the 7zip folder (and -recurse collecting $files)



    So change the line



    $Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}


    and append



    | Select-Object -ExpandProperty FullName


    A slightly reformatted verson ofyour source:



    Function Zip{
    Param (
    [string]$zipFile,
    [string]$toBeZipped
    )
    & "C:Program Files7-Zip7z.exe" A -tzip $zipFile $toBeZipped | Out-Null
    }
    $Days = "60"
    $LastWrite = (Get-Date).Date.AddDays(-$Days)

    $TargetFolder = "$($ENV:USERPROFILE)Downloads*"

    $Files = Get-Childitem $TargetFolder -Recurse |
    Where {$_.LastWriteTime -le $LastWrite} |
    Select-Object -ExpandProperty FullName
    $Files
    Zip "$($ENV:USERPROFILE)DesktopTEST.zip" $Files





    share|improve this answer


























    • Ok. It worked. However if I try it again, and there isn't any folders that meet the criteria to be zipped, it will zip the contents of the 7zip program. Is there anyway to prevent that?

      – techguy1029
      Nov 20 '18 at 19:41






    • 1





      Sorry I can't follow I just tested my posted version with the suggest edits and it run's here without flaw. I agree with mklement0 that it's better NOT to change the path to 7zip folder to avid zipping that folder as suggested by @mklement0

      – LotPings
      Nov 20 '18 at 19:43











    • Yes, the posted version works. However, lets say I run this in a file that doesn't have any files to be zipped, what will happen is that all of the contents of the 7-zip program are copied into the ZIP folder.

      – techguy1029
      Nov 20 '18 at 19:54











    • Make the params mandatory Param ( [Parameter(Position=0,mandatory=$true)] [string]$zipFile, [Parameter(Position=1,mandatory=$true)] [string]$toBeZipped )

      – LotPings
      Nov 20 '18 at 20:02








    • 1





      @LotPings: Here the objects indeed stringify to file names only, which is the problem, but whether they stringify to mere file names (.Name) or full paths (.FullName) generally depends on the specifics of the Get-ChildItem call, (very) unfortunately - I've tried to summarize the rules in my answer.

      – mklement0
      Nov 20 '18 at 20:35











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53399457%2fpowershell-script-not-zipping-correct-files%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3














    Pass the files as full paths to the Zip function, using their .FullName property (PSv3+ syntax):



    Zip C:UsersAdminDesktopTEST.zip $Files.FullName




    The problem is that the [System.IO.FileInfo] instances returned by Get-ChildItem situationally[1] stringify to their file names only, which is what happened in your case, so your Zip function then interpreted the $toBeZipped values as relative to the current location, which is C:Program Files7-Zip at that point.



    That said, it's better not to use Set-Location in your function altogether, so that in the event that you do want to pass actual relative paths, they are correctly interpreted as relative to the current location:



    Function Zip {
    Param
    (
    [Parameter(Mandatory)] # make sure a value is passed
    [string]$zipFile
    ,
    [Parameter(Mandatory)] # make sure a value is passed
    [string]$toBeZipped
    )
    # Don't change the location, use & to invoke 7z by its full path.
    $null = & "C:Program Files7-Zip7z.exe" A -tzip $zipFile $toBeZipped
    # You may want to add error handling here.
    }




    [1] When Get-ChildItem output stringifies to file names only:



    Note:





    • Get-Item output always stringifies to the full path, fortunately.


    • In PowerShell Core, Get-ChildItem too always stringifies to the full path, which is commendable, but it's unclear whether the change was intentional.


    The following therefore only applies to Get-ChildItem in Windows PowerShell:



    The problem is twofold:




    • Even PowerShell's built-in cmdlets bind file / directory arguments (parameter values - as opposed to input via the pipeline) not as objects, but as strings (changing this behavior is being discussed in this GitHub issue).


    • Therefore, for robust argument-passing, you need to ensure that your Get-ChildItem output consistently stringifies to full paths, which Get-ChildItem does not guarantee - and it's easy to forget when name-only stringification occurs of even that you need to pay attention to it at all.



    Always passing the .FullName property values instead is the simplest workaround or, for reliable operation with any PowerShell provider, not just the filesystem, .PSPath.



    [System.IO.FileInfo] and [System.IO.DirectoryInfo] instances output by a Get-ChildItem command stringify to their file names only, if and only if:




    • If one or more literal directory paths are passed to -LiteralPath or -Path (possibly as the 1st positional argument) or no path at all is passed (target the current location); that is, if the contents of directories are enumerated.


    • and does not also use the -Include / -Exclude parameters (whether -Filter is used makes no difference).



    • By contrast, whether or not the following are also present makes no difference:





      • -Filter (optionally as the 2nd positional argument, but note that specifying a wildcard expression such as *.txt as the 1st (and possibly only) positional argument binds to the -Path parameter)


      • -Recurse (by itself, but note that it is often combined with -Include / -Exclude)




    Example commands:



    # NAME-ONLY stringification:

    Get-ChildItem | % ToString # no target path

    Get-ChildItem . | % ToString # path is literal dir.

    Get-ChildItem . *.txt | % ToString # path is literal dir., combined with -Filter

    # FULL PATH stringification:

    Get-ChildItem foo* | % ToString # non-literal path (wildcard)

    Get-ChildItem -Recurse -Include *.txt | % ToString # use of -Include

    Get-ChildItem file.txt | % ToString # *file* path





    share|improve this answer






























      3














      Pass the files as full paths to the Zip function, using their .FullName property (PSv3+ syntax):



      Zip C:UsersAdminDesktopTEST.zip $Files.FullName




      The problem is that the [System.IO.FileInfo] instances returned by Get-ChildItem situationally[1] stringify to their file names only, which is what happened in your case, so your Zip function then interpreted the $toBeZipped values as relative to the current location, which is C:Program Files7-Zip at that point.



      That said, it's better not to use Set-Location in your function altogether, so that in the event that you do want to pass actual relative paths, they are correctly interpreted as relative to the current location:



      Function Zip {
      Param
      (
      [Parameter(Mandatory)] # make sure a value is passed
      [string]$zipFile
      ,
      [Parameter(Mandatory)] # make sure a value is passed
      [string]$toBeZipped
      )
      # Don't change the location, use & to invoke 7z by its full path.
      $null = & "C:Program Files7-Zip7z.exe" A -tzip $zipFile $toBeZipped
      # You may want to add error handling here.
      }




      [1] When Get-ChildItem output stringifies to file names only:



      Note:





      • Get-Item output always stringifies to the full path, fortunately.


      • In PowerShell Core, Get-ChildItem too always stringifies to the full path, which is commendable, but it's unclear whether the change was intentional.


      The following therefore only applies to Get-ChildItem in Windows PowerShell:



      The problem is twofold:




      • Even PowerShell's built-in cmdlets bind file / directory arguments (parameter values - as opposed to input via the pipeline) not as objects, but as strings (changing this behavior is being discussed in this GitHub issue).


      • Therefore, for robust argument-passing, you need to ensure that your Get-ChildItem output consistently stringifies to full paths, which Get-ChildItem does not guarantee - and it's easy to forget when name-only stringification occurs of even that you need to pay attention to it at all.



      Always passing the .FullName property values instead is the simplest workaround or, for reliable operation with any PowerShell provider, not just the filesystem, .PSPath.



      [System.IO.FileInfo] and [System.IO.DirectoryInfo] instances output by a Get-ChildItem command stringify to their file names only, if and only if:




      • If one or more literal directory paths are passed to -LiteralPath or -Path (possibly as the 1st positional argument) or no path at all is passed (target the current location); that is, if the contents of directories are enumerated.


      • and does not also use the -Include / -Exclude parameters (whether -Filter is used makes no difference).



      • By contrast, whether or not the following are also present makes no difference:





        • -Filter (optionally as the 2nd positional argument, but note that specifying a wildcard expression such as *.txt as the 1st (and possibly only) positional argument binds to the -Path parameter)


        • -Recurse (by itself, but note that it is often combined with -Include / -Exclude)




      Example commands:



      # NAME-ONLY stringification:

      Get-ChildItem | % ToString # no target path

      Get-ChildItem . | % ToString # path is literal dir.

      Get-ChildItem . *.txt | % ToString # path is literal dir., combined with -Filter

      # FULL PATH stringification:

      Get-ChildItem foo* | % ToString # non-literal path (wildcard)

      Get-ChildItem -Recurse -Include *.txt | % ToString # use of -Include

      Get-ChildItem file.txt | % ToString # *file* path





      share|improve this answer




























        3












        3








        3







        Pass the files as full paths to the Zip function, using their .FullName property (PSv3+ syntax):



        Zip C:UsersAdminDesktopTEST.zip $Files.FullName




        The problem is that the [System.IO.FileInfo] instances returned by Get-ChildItem situationally[1] stringify to their file names only, which is what happened in your case, so your Zip function then interpreted the $toBeZipped values as relative to the current location, which is C:Program Files7-Zip at that point.



        That said, it's better not to use Set-Location in your function altogether, so that in the event that you do want to pass actual relative paths, they are correctly interpreted as relative to the current location:



        Function Zip {
        Param
        (
        [Parameter(Mandatory)] # make sure a value is passed
        [string]$zipFile
        ,
        [Parameter(Mandatory)] # make sure a value is passed
        [string]$toBeZipped
        )
        # Don't change the location, use & to invoke 7z by its full path.
        $null = & "C:Program Files7-Zip7z.exe" A -tzip $zipFile $toBeZipped
        # You may want to add error handling here.
        }




        [1] When Get-ChildItem output stringifies to file names only:



        Note:





        • Get-Item output always stringifies to the full path, fortunately.


        • In PowerShell Core, Get-ChildItem too always stringifies to the full path, which is commendable, but it's unclear whether the change was intentional.


        The following therefore only applies to Get-ChildItem in Windows PowerShell:



        The problem is twofold:




        • Even PowerShell's built-in cmdlets bind file / directory arguments (parameter values - as opposed to input via the pipeline) not as objects, but as strings (changing this behavior is being discussed in this GitHub issue).


        • Therefore, for robust argument-passing, you need to ensure that your Get-ChildItem output consistently stringifies to full paths, which Get-ChildItem does not guarantee - and it's easy to forget when name-only stringification occurs of even that you need to pay attention to it at all.



        Always passing the .FullName property values instead is the simplest workaround or, for reliable operation with any PowerShell provider, not just the filesystem, .PSPath.



        [System.IO.FileInfo] and [System.IO.DirectoryInfo] instances output by a Get-ChildItem command stringify to their file names only, if and only if:




        • If one or more literal directory paths are passed to -LiteralPath or -Path (possibly as the 1st positional argument) or no path at all is passed (target the current location); that is, if the contents of directories are enumerated.


        • and does not also use the -Include / -Exclude parameters (whether -Filter is used makes no difference).



        • By contrast, whether or not the following are also present makes no difference:





          • -Filter (optionally as the 2nd positional argument, but note that specifying a wildcard expression such as *.txt as the 1st (and possibly only) positional argument binds to the -Path parameter)


          • -Recurse (by itself, but note that it is often combined with -Include / -Exclude)




        Example commands:



        # NAME-ONLY stringification:

        Get-ChildItem | % ToString # no target path

        Get-ChildItem . | % ToString # path is literal dir.

        Get-ChildItem . *.txt | % ToString # path is literal dir., combined with -Filter

        # FULL PATH stringification:

        Get-ChildItem foo* | % ToString # non-literal path (wildcard)

        Get-ChildItem -Recurse -Include *.txt | % ToString # use of -Include

        Get-ChildItem file.txt | % ToString # *file* path





        share|improve this answer















        Pass the files as full paths to the Zip function, using their .FullName property (PSv3+ syntax):



        Zip C:UsersAdminDesktopTEST.zip $Files.FullName




        The problem is that the [System.IO.FileInfo] instances returned by Get-ChildItem situationally[1] stringify to their file names only, which is what happened in your case, so your Zip function then interpreted the $toBeZipped values as relative to the current location, which is C:Program Files7-Zip at that point.



        That said, it's better not to use Set-Location in your function altogether, so that in the event that you do want to pass actual relative paths, they are correctly interpreted as relative to the current location:



        Function Zip {
        Param
        (
        [Parameter(Mandatory)] # make sure a value is passed
        [string]$zipFile
        ,
        [Parameter(Mandatory)] # make sure a value is passed
        [string]$toBeZipped
        )
        # Don't change the location, use & to invoke 7z by its full path.
        $null = & "C:Program Files7-Zip7z.exe" A -tzip $zipFile $toBeZipped
        # You may want to add error handling here.
        }




        [1] When Get-ChildItem output stringifies to file names only:



        Note:





        • Get-Item output always stringifies to the full path, fortunately.


        • In PowerShell Core, Get-ChildItem too always stringifies to the full path, which is commendable, but it's unclear whether the change was intentional.


        The following therefore only applies to Get-ChildItem in Windows PowerShell:



        The problem is twofold:




        • Even PowerShell's built-in cmdlets bind file / directory arguments (parameter values - as opposed to input via the pipeline) not as objects, but as strings (changing this behavior is being discussed in this GitHub issue).


        • Therefore, for robust argument-passing, you need to ensure that your Get-ChildItem output consistently stringifies to full paths, which Get-ChildItem does not guarantee - and it's easy to forget when name-only stringification occurs of even that you need to pay attention to it at all.



        Always passing the .FullName property values instead is the simplest workaround or, for reliable operation with any PowerShell provider, not just the filesystem, .PSPath.



        [System.IO.FileInfo] and [System.IO.DirectoryInfo] instances output by a Get-ChildItem command stringify to their file names only, if and only if:




        • If one or more literal directory paths are passed to -LiteralPath or -Path (possibly as the 1st positional argument) or no path at all is passed (target the current location); that is, if the contents of directories are enumerated.


        • and does not also use the -Include / -Exclude parameters (whether -Filter is used makes no difference).



        • By contrast, whether or not the following are also present makes no difference:





          • -Filter (optionally as the 2nd positional argument, but note that specifying a wildcard expression such as *.txt as the 1st (and possibly only) positional argument binds to the -Path parameter)


          • -Recurse (by itself, but note that it is often combined with -Include / -Exclude)




        Example commands:



        # NAME-ONLY stringification:

        Get-ChildItem | % ToString # no target path

        Get-ChildItem . | % ToString # path is literal dir.

        Get-ChildItem . *.txt | % ToString # path is literal dir., combined with -Filter

        # FULL PATH stringification:

        Get-ChildItem foo* | % ToString # non-literal path (wildcard)

        Get-ChildItem -Recurse -Include *.txt | % ToString # use of -Include

        Get-ChildItem file.txt | % ToString # *file* path






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 20 '18 at 20:40

























        answered Nov 20 '18 at 19:17









        mklement0mklement0

        132k21246284




        132k21246284

























            1














            If you (temporarily) disable the |Out-Null you'll see what error msg pass along.

            $Files contains objects not just an array of file names.



            By default powershell tries to stringify this using the Name property which doesn't contain the path - so 7zip can't find the files as you also change the path to the 7zip folder (and -recurse collecting $files)



            So change the line



            $Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}


            and append



            | Select-Object -ExpandProperty FullName


            A slightly reformatted verson ofyour source:



            Function Zip{
            Param (
            [string]$zipFile,
            [string]$toBeZipped
            )
            & "C:Program Files7-Zip7z.exe" A -tzip $zipFile $toBeZipped | Out-Null
            }
            $Days = "60"
            $LastWrite = (Get-Date).Date.AddDays(-$Days)

            $TargetFolder = "$($ENV:USERPROFILE)Downloads*"

            $Files = Get-Childitem $TargetFolder -Recurse |
            Where {$_.LastWriteTime -le $LastWrite} |
            Select-Object -ExpandProperty FullName
            $Files
            Zip "$($ENV:USERPROFILE)DesktopTEST.zip" $Files





            share|improve this answer


























            • Ok. It worked. However if I try it again, and there isn't any folders that meet the criteria to be zipped, it will zip the contents of the 7zip program. Is there anyway to prevent that?

              – techguy1029
              Nov 20 '18 at 19:41






            • 1





              Sorry I can't follow I just tested my posted version with the suggest edits and it run's here without flaw. I agree with mklement0 that it's better NOT to change the path to 7zip folder to avid zipping that folder as suggested by @mklement0

              – LotPings
              Nov 20 '18 at 19:43











            • Yes, the posted version works. However, lets say I run this in a file that doesn't have any files to be zipped, what will happen is that all of the contents of the 7-zip program are copied into the ZIP folder.

              – techguy1029
              Nov 20 '18 at 19:54











            • Make the params mandatory Param ( [Parameter(Position=0,mandatory=$true)] [string]$zipFile, [Parameter(Position=1,mandatory=$true)] [string]$toBeZipped )

              – LotPings
              Nov 20 '18 at 20:02








            • 1





              @LotPings: Here the objects indeed stringify to file names only, which is the problem, but whether they stringify to mere file names (.Name) or full paths (.FullName) generally depends on the specifics of the Get-ChildItem call, (very) unfortunately - I've tried to summarize the rules in my answer.

              – mklement0
              Nov 20 '18 at 20:35
















            1














            If you (temporarily) disable the |Out-Null you'll see what error msg pass along.

            $Files contains objects not just an array of file names.



            By default powershell tries to stringify this using the Name property which doesn't contain the path - so 7zip can't find the files as you also change the path to the 7zip folder (and -recurse collecting $files)



            So change the line



            $Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}


            and append



            | Select-Object -ExpandProperty FullName


            A slightly reformatted verson ofyour source:



            Function Zip{
            Param (
            [string]$zipFile,
            [string]$toBeZipped
            )
            & "C:Program Files7-Zip7z.exe" A -tzip $zipFile $toBeZipped | Out-Null
            }
            $Days = "60"
            $LastWrite = (Get-Date).Date.AddDays(-$Days)

            $TargetFolder = "$($ENV:USERPROFILE)Downloads*"

            $Files = Get-Childitem $TargetFolder -Recurse |
            Where {$_.LastWriteTime -le $LastWrite} |
            Select-Object -ExpandProperty FullName
            $Files
            Zip "$($ENV:USERPROFILE)DesktopTEST.zip" $Files





            share|improve this answer


























            • Ok. It worked. However if I try it again, and there isn't any folders that meet the criteria to be zipped, it will zip the contents of the 7zip program. Is there anyway to prevent that?

              – techguy1029
              Nov 20 '18 at 19:41






            • 1





              Sorry I can't follow I just tested my posted version with the suggest edits and it run's here without flaw. I agree with mklement0 that it's better NOT to change the path to 7zip folder to avid zipping that folder as suggested by @mklement0

              – LotPings
              Nov 20 '18 at 19:43











            • Yes, the posted version works. However, lets say I run this in a file that doesn't have any files to be zipped, what will happen is that all of the contents of the 7-zip program are copied into the ZIP folder.

              – techguy1029
              Nov 20 '18 at 19:54











            • Make the params mandatory Param ( [Parameter(Position=0,mandatory=$true)] [string]$zipFile, [Parameter(Position=1,mandatory=$true)] [string]$toBeZipped )

              – LotPings
              Nov 20 '18 at 20:02








            • 1





              @LotPings: Here the objects indeed stringify to file names only, which is the problem, but whether they stringify to mere file names (.Name) or full paths (.FullName) generally depends on the specifics of the Get-ChildItem call, (very) unfortunately - I've tried to summarize the rules in my answer.

              – mklement0
              Nov 20 '18 at 20:35














            1












            1








            1







            If you (temporarily) disable the |Out-Null you'll see what error msg pass along.

            $Files contains objects not just an array of file names.



            By default powershell tries to stringify this using the Name property which doesn't contain the path - so 7zip can't find the files as you also change the path to the 7zip folder (and -recurse collecting $files)



            So change the line



            $Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}


            and append



            | Select-Object -ExpandProperty FullName


            A slightly reformatted verson ofyour source:



            Function Zip{
            Param (
            [string]$zipFile,
            [string]$toBeZipped
            )
            & "C:Program Files7-Zip7z.exe" A -tzip $zipFile $toBeZipped | Out-Null
            }
            $Days = "60"
            $LastWrite = (Get-Date).Date.AddDays(-$Days)

            $TargetFolder = "$($ENV:USERPROFILE)Downloads*"

            $Files = Get-Childitem $TargetFolder -Recurse |
            Where {$_.LastWriteTime -le $LastWrite} |
            Select-Object -ExpandProperty FullName
            $Files
            Zip "$($ENV:USERPROFILE)DesktopTEST.zip" $Files





            share|improve this answer















            If you (temporarily) disable the |Out-Null you'll see what error msg pass along.

            $Files contains objects not just an array of file names.



            By default powershell tries to stringify this using the Name property which doesn't contain the path - so 7zip can't find the files as you also change the path to the 7zip folder (and -recurse collecting $files)



            So change the line



            $Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}


            and append



            | Select-Object -ExpandProperty FullName


            A slightly reformatted verson ofyour source:



            Function Zip{
            Param (
            [string]$zipFile,
            [string]$toBeZipped
            )
            & "C:Program Files7-Zip7z.exe" A -tzip $zipFile $toBeZipped | Out-Null
            }
            $Days = "60"
            $LastWrite = (Get-Date).Date.AddDays(-$Days)

            $TargetFolder = "$($ENV:USERPROFILE)Downloads*"

            $Files = Get-Childitem $TargetFolder -Recurse |
            Where {$_.LastWriteTime -le $LastWrite} |
            Select-Object -ExpandProperty FullName
            $Files
            Zip "$($ENV:USERPROFILE)DesktopTEST.zip" $Files






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 20 '18 at 19:47

























            answered Nov 20 '18 at 19:17









            LotPingsLotPings

            19.3k61532




            19.3k61532













            • Ok. It worked. However if I try it again, and there isn't any folders that meet the criteria to be zipped, it will zip the contents of the 7zip program. Is there anyway to prevent that?

              – techguy1029
              Nov 20 '18 at 19:41






            • 1





              Sorry I can't follow I just tested my posted version with the suggest edits and it run's here without flaw. I agree with mklement0 that it's better NOT to change the path to 7zip folder to avid zipping that folder as suggested by @mklement0

              – LotPings
              Nov 20 '18 at 19:43











            • Yes, the posted version works. However, lets say I run this in a file that doesn't have any files to be zipped, what will happen is that all of the contents of the 7-zip program are copied into the ZIP folder.

              – techguy1029
              Nov 20 '18 at 19:54











            • Make the params mandatory Param ( [Parameter(Position=0,mandatory=$true)] [string]$zipFile, [Parameter(Position=1,mandatory=$true)] [string]$toBeZipped )

              – LotPings
              Nov 20 '18 at 20:02








            • 1





              @LotPings: Here the objects indeed stringify to file names only, which is the problem, but whether they stringify to mere file names (.Name) or full paths (.FullName) generally depends on the specifics of the Get-ChildItem call, (very) unfortunately - I've tried to summarize the rules in my answer.

              – mklement0
              Nov 20 '18 at 20:35



















            • Ok. It worked. However if I try it again, and there isn't any folders that meet the criteria to be zipped, it will zip the contents of the 7zip program. Is there anyway to prevent that?

              – techguy1029
              Nov 20 '18 at 19:41






            • 1





              Sorry I can't follow I just tested my posted version with the suggest edits and it run's here without flaw. I agree with mklement0 that it's better NOT to change the path to 7zip folder to avid zipping that folder as suggested by @mklement0

              – LotPings
              Nov 20 '18 at 19:43











            • Yes, the posted version works. However, lets say I run this in a file that doesn't have any files to be zipped, what will happen is that all of the contents of the 7-zip program are copied into the ZIP folder.

              – techguy1029
              Nov 20 '18 at 19:54











            • Make the params mandatory Param ( [Parameter(Position=0,mandatory=$true)] [string]$zipFile, [Parameter(Position=1,mandatory=$true)] [string]$toBeZipped )

              – LotPings
              Nov 20 '18 at 20:02








            • 1





              @LotPings: Here the objects indeed stringify to file names only, which is the problem, but whether they stringify to mere file names (.Name) or full paths (.FullName) generally depends on the specifics of the Get-ChildItem call, (very) unfortunately - I've tried to summarize the rules in my answer.

              – mklement0
              Nov 20 '18 at 20:35

















            Ok. It worked. However if I try it again, and there isn't any folders that meet the criteria to be zipped, it will zip the contents of the 7zip program. Is there anyway to prevent that?

            – techguy1029
            Nov 20 '18 at 19:41





            Ok. It worked. However if I try it again, and there isn't any folders that meet the criteria to be zipped, it will zip the contents of the 7zip program. Is there anyway to prevent that?

            – techguy1029
            Nov 20 '18 at 19:41




            1




            1





            Sorry I can't follow I just tested my posted version with the suggest edits and it run's here without flaw. I agree with mklement0 that it's better NOT to change the path to 7zip folder to avid zipping that folder as suggested by @mklement0

            – LotPings
            Nov 20 '18 at 19:43





            Sorry I can't follow I just tested my posted version with the suggest edits and it run's here without flaw. I agree with mklement0 that it's better NOT to change the path to 7zip folder to avid zipping that folder as suggested by @mklement0

            – LotPings
            Nov 20 '18 at 19:43













            Yes, the posted version works. However, lets say I run this in a file that doesn't have any files to be zipped, what will happen is that all of the contents of the 7-zip program are copied into the ZIP folder.

            – techguy1029
            Nov 20 '18 at 19:54





            Yes, the posted version works. However, lets say I run this in a file that doesn't have any files to be zipped, what will happen is that all of the contents of the 7-zip program are copied into the ZIP folder.

            – techguy1029
            Nov 20 '18 at 19:54













            Make the params mandatory Param ( [Parameter(Position=0,mandatory=$true)] [string]$zipFile, [Parameter(Position=1,mandatory=$true)] [string]$toBeZipped )

            – LotPings
            Nov 20 '18 at 20:02







            Make the params mandatory Param ( [Parameter(Position=0,mandatory=$true)] [string]$zipFile, [Parameter(Position=1,mandatory=$true)] [string]$toBeZipped )

            – LotPings
            Nov 20 '18 at 20:02






            1




            1





            @LotPings: Here the objects indeed stringify to file names only, which is the problem, but whether they stringify to mere file names (.Name) or full paths (.FullName) generally depends on the specifics of the Get-ChildItem call, (very) unfortunately - I've tried to summarize the rules in my answer.

            – mklement0
            Nov 20 '18 at 20:35





            @LotPings: Here the objects indeed stringify to file names only, which is the problem, but whether they stringify to mere file names (.Name) or full paths (.FullName) generally depends on the specifics of the Get-ChildItem call, (very) unfortunately - I've tried to summarize the rules in my answer.

            – mklement0
            Nov 20 '18 at 20:35


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53399457%2fpowershell-script-not-zipping-correct-files%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            Tangent Lines Diagram Along Smooth Curve

            Yusuf al-Mu'taman ibn Hud

            Zucchini