I am trying to zip files that are in directories that have subdirectories and I can't figure out how to zip the files and not the subdirectories.
Here is the current setup:
C:\users\user\appdata\local\folder\
Inside of this folder, I need 3 out of the 20 or so folders that are in there so I used the Get-Childitem to accomplish this:
GCI C:\users\user\appdata\local\folder | ? {$_.name -like "*folder*}
Now that I have that, I don't want the subdirectories and just want the files that are sitting in the folder itself. I have not found a way to do this, but I have gotten close with using this:
& "C:\program files\7-zip\7z.exe" "a" "D:\TestBackup\Zipfile.7z" (GCI C:\users\user\appdata\local\folder | ? {$_.name -like "*folder*} | select -expandproperty FullName)
But this gives me the entire contents of the folder. I want to keep the structure so that it looks like this:
folder 1\files
folder 2\files
folder 3\files
I hope I am explaining myself well. The files are all different types of extensions so I was wanting a blanket way to do this or to exclude the subdirectories when zipping.
CodePudding user response:
I had to consult the FAQ to get this right:
7-Zip stores only relative paths of files (without drive letter prefix). You can change current folder to folder that is common for all files that you want to compress and then you can use relative paths:
cd /D C:\dir1\ 7z.exe a c:\a.7z file1.txt dir2\file2.txt
Solution:
# Set base directory that is common for all files
Push-Location 'C:\users\user\appdata\local\folder'
# Get names of directories that match filter
$folderNames = (Get-ChildItem -Directory -Filter '*folder*').Name
# Call 7-zip, passing the list of directory names.
& 'C:\Program Files\7-Zip\7z.exe' a 'D:\TestBackup\Zipfile.7z' $folderNames
# Restore current directory
Pop-Location
Remarks:
Push-Location
sets the current directory, whilePop-Location
restores the previous current directory. Changing the current directory is crucial for this solution, as explained by the 7-zip FAQ. It is also the only way to set the base directory forResolve-Path -Relative
.- Pass
-Directory
or-File
toGet-ChildItem
if you are only interested in either directories or files. - Use
-Filter
instead ofWhere-Object
(alias?
) if you only need simple wildcard filtering.-Filter
is faster because it uses the FileSystem provider which filters at a lower API level, which avoids PowerShell overhead.