Home > Software design >  Add files from selected directories to 7-zip archive while keeping relative directory structure in a
Add files from selected directories to 7-zip archive while keeping relative directory structure in a

Time:06-16

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, while Pop-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 for Resolve-Path -Relative.
  • Pass -Directory or -File to Get-ChildItem if you are only interested in either directories or files.
  • Use -Filter instead of Where-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.
  • Related