Windows 10 powershell ise compress-archive files at root .in .zip - windows

With Windows(10) powerShell ise,
Is it possible to zip the content of a folder, like it does with command 'Compress-Archive', but not encapsuled it in a root folder on th zip ?
(Get the files at root in the zip)
eg: - myFolder { index.html, mycss.css, myConn.php}
used command: -DestinationPath C:\wamp64\www\myFolder\myZip.zip -Path C:\wamp64\www\myFolder
actual result in myZip.zip: { - myFolder { index.html, mycss.css, myConn.php} }
desired result in myZip.zip: { index.html, mycss.css, myConn.php}
ps: i tried search options for that but not found.

With your -Path being a folder you explicitly include it in the archive.
As already mentioned by Tomalak giving a wildcard changes that.
Compress-Archive -Path C:\wamp64\www\myFolder\* -DestinationPath C:\wamp64\www\myFolder\myZip.zip
If you supply the parameters in the proper positional order, you don't have to name them:
Compress-Archive C:\wamp64\www\myFolder\* C:\wamp64\www\myFolder\myZip.zip
To have better control over what is archived you can pipe the source(s) to Compress-Archive
(for example to exclude possible subdirectories)
Get-ChildItem C:\wamp64\www\myFolder\* -File | Compress-Archive C:\wamp64\www\myFolder\myZip.zip

Compress-Archive -DestinationPath C:\wamp64\www\myFolder\myZip.zip -Path C:\wamp64\www\myFolder\*
Complete command to achieve this goal

Related

How can I get a list of folders/subfolders that DOES NOT contain a specific type of file?

For example, I wanted to print a list of folders which contain an .html file. Correct me if I am wrong, but this worked for me:
dir /S *.html > C:\Users\PC\Desktop\with-html.txt
Now I would like to find the folders which do not contain .html files.
How do I go about that?
EDIT:
The folders are structured in a way that only the child folders (last subfolder) have any kind of files. I would like to get a list of directories to those subfolders. So the above command line is giving me:
C:\...\ml\regression\lasso-regression
C:\...\ml\regression\linear-regression
There is not output just C:\...\ml or C:\...\ml\regression.
The folder structure looks like this:
C:\...\ml
classification
regression
lasso-regression
linear-regression
There are about 10 folders in folder ml and no files. There are again about 10 folders in second folder level where C:\...\ml\regression\linear-regression contains an HTML file while C:\...\ml\regression\lasso-regression does not contain a file with file extension .html. Only the folders in last level of the folders tree have files at all.
I'd be grateful getting just the list of the last folders in folders tree not containing a file with file extension .html.
I basically output the above command line into a .csv file, filtered it with MS Excel, and have now a list of folders with .html file(s). I'm basically working with R-markdown files, and it'll be a status report, the folders list with .html files is what I have completed already. So in need now only the opposite folders list.
Not difficult using PowerShell.
Get-ChildItem -Recurse -Directory |
ForEach-Object {
if ((Get-ChildItem -File -Path $_.FullName -Filter '*.html').Length -eq 0) { $_.FullName }
}
If you must run this in a .bat file script, the following might be used.
#powershell.exe -NoLogo -NoProfile -Command ^
"Get-ChildItem -Recurse -Directory |" ^
"ForEach-Object {" ^
"if ((Get-ChildItem -File -Path $_.FullName -Filter '*.html').Length -eq 0) { $_.FullName }" ^
"}"

Unzip Multiple Files into Different Directories

I have multiple zip files.
They are called folder(1).zip, folder(2).zip, folder(3).zip. Using PowerShell, when I attempt to unzip them all into unique folders using this...
Get-ChildItem 'c:\users\name\downloads' -Filter *.zip | Expand-Archive -DestinationPath 'c:\users\name\downloads' -Force
I get all of the files into one folder called "folder". How can I get the zip folders to unzip into separate folders?
Bonus question, is there a way, as part of this process, to rename each folder as it's coming out so folder(1).zip becomes Name-Here, folder(2).zip becomes Other-Name-Here, etc?
Thanks!
Because you specify only one destination path they will all be extracted into c:\users\name\downloads. I suppose the zip archives each contain a folder named "folder", so all contents from all archives end up together in c:\users\name\downloads\folder
You would have to specify a different destination path for each archive. Not sure what your naming convention should be, I have used a simple counter:
$counter = 0
Get-ChildItem 'c:\users\name\downloads' -Filter *.zip | foreach {
$destination = Join-Path $_.DirectoryName ("YourName" + $counter++)
Expand-Archive $_.FullName -DestinationPath $destination
}
Of course I suppose, now every of those folders will have the subfolder "folder", but if that's how the archives are built there's not really a way to change that. If you are absolutely sure that all archives have that subfolder, you could do something like this:
$counter = 0
Get-ChildItem 'c:\users\name\downloads' -Filter *.zip | foreach {
# expand to the root folder first
Expand-Archive $_.FullName -DestinationPath $_.DirectoryName
# now rename the extracted "folder" to whatever you like
Rename-Item (Join-Path $_.DirectoryName "folder") -NewName ("YourName" + $counter++)
}

Check if multiple directories exist in Powershell and then execute command

I am using this command to remove multiple files in two different directories:
Remove-Item -path c:\tmp\folder1\*, c:\tmp\folder1\* -Force -Recurse
both folders contain some zip files and sub folders which i want te remove
I need to check if those folders (folder1 and folder2) exist and not empty before executing this command. Can't figure it out :(
Any help would be appreciated.
If you want to check multiple conditions with an if then -and the results:
if ((Test-Path 'C:\tmp\folder1\*') -and
(Test-Path 'C:\tmp\folder2\*') ){
Remove-Item -path c:\tmp\folder1\*, c:\tmp\folder1\* -Force -Recurse
} else {
"not all conditions met."
}
An explicit Test-Path for the folders isn't neccessary as it is implied with items in the folders.
I suggest using the command "test-path", and then using a | (a pipe) to output a true or false value for proceeding to executing the command that you are using to delete a directory.

Batch file to compress subdirectories individually with Windows native tools

I've seen variations of this question answered, but typically using something like 7zip. I'm trying to find a solution that will work with the capabilities that come with windows absent any additional tools.
I have a directory that contains several hundred subdirectories. I need to individually compress each subdirectory....so I'll wind up with several hundred zip files, one per subdirectory. This is on a machine at work where I don't have administrative privileges to install new software...hence the desire to stay away from 7zip, winRar, etc.
If this has already been answered elsewhere, my apologies...
Never tried that myself, but there is Compress-Archive:
The Compress-Archive cmdlet creates a zipped (or compressed) archive file from one or more specified files or folders. An archive file allows multiple files to be packaged, and optionally compressed, into a single zipped file for easier distribution and storage. An archive file can be compressed by using the compression algorithm specified by the CompressionLevel parameter.
Because Compress-Archive relies upon the Microsoft .NET Framework API System.IO.Compression.ZipArchive to compress files, the maximum file size that you can compress by using Compress-Archive is currently 2 GB. This is a limitation of the underlying API.
Here's a sample script I just hacked together:
# configure as needed
$source = "c:\temp"
$target = "d:\temp\test"
# grab source file names and list them
$files = gci $source -recurse
$files
# target exists?
if( -not (test-path $target)) {
new-item $target -type directory
}
# compress, I am using -force here to overwrite existing files
$files | foreach{
$dest = "$target\" + $_.name + ".zip"
compress-archive $_ $dest -CompressionLevel Optimal -force
}
# list target dir contents
gci $target -recurse
You may have to improve it a bit when it comes to subfolders. In the above version, subfolders are compressed as a whole into a single file. This might not exactly be what you want.
Get-ChildItem c:\path\of\your\folder | ForEach-Object {
$path = $_.FullName
Compress-Archive -Path $path -DestinationPath "$path.zip"
}
I put this, as a quick snippet. Don't hesitate to comment if this does not fit with your request.
In a folder X, there are subfolders Y1, Y2...
Y1.zip, Y2.zip... will be created.
use PowerShell go the the path that you would like to compress, do:
$folderlist = Get-ChildItem "."
foreach ($Folder in $folderlist) { Compress-Archive -path $Folder.Name -destinationPath "$($Folder.Name).zip"}

powershell copy-item doesn't copy when filter is used

I'm trying to copy files using copy-item. Specifically, I want to copy files with a particular extension that are within a folder or its subfolders to another location, and to retain the subfolder hierarchy. I've tried using -filter and -include to specify the file extension, but no files are copied.
My source and destination paths are stored in variables $packageSourcePath and $objPath. When called, $packageSourcePath will be like the following ".\src\projects\Project1\PackageFiles" and $objPath will be like the following ".\bld\Project1\obj".
The command I've tried using is this:
Copy-Item -Path $packageSourcePath\* -Filter *.resw -Destination $objPath -Recurse
I've also tried variations, such as leaving off * from the path, or using -Include instead of -Filter. Nothing works. If I leave out the -Filter argument, then files copy, but all of the files are copied. I only want files with the particular extension.
I've given up on Copy-Item. JohnLBevan's answer didn't actually do what I want since all files in the source root get copied, even though they don't match the filter. I tried piping Convert-Path | Select-String | Copy-Item but still got all files in the source root being copied.
A contact in a different context provided a couple of suggestions:
1)
Get-ChildItem -Force -Recurse -ErrorAction Ignore -Path $packageSourcePath -Filter *.resw | % {
$src = $_.FullName
$dst = Join-Path $objPath $src.SubString($packageSourcePath.Length)
echo "copy ""$src"" ""$dst"""
}
I think this is a bit harder to follow, hence less maintainable for the next person (likely another PS-neophyte like me) a year from now. ("Why is the -ErrorAction parameter needed here? What's the behaviour of the Substring() method, and why can't I find that using Get-Help?")
This suggestion is a bit clearer, after re-familiarizing with attrib and checking the effect of the xcopy switches:
2)
cd $packageSourcePath
attrib -a /s
attrib +a *.resw /s
xcopy /eidlm $packageSourcePath $objPath
But if we're going to use xcopy, we don't need to call attrib:
xcopy $packageSourcePath*.resw $objPath /s /i > $null
The only problem with this for my scenario is that xcopy emits an error if no matching files are found. My script is being used for a VSTS build task, and the xcopy errors cause the build task to fail. (For that reason, I'm guess that suggestion 2 also wouldn't work for me.)
So, I've opted for this:
# In PS version 5.1, nothing gets copied using Copy-Item $packageSourcePath\* -Filter *.resw ...
# so resorting to using xcopy, which mostly works. The one issue is that xcopy will output an
# error if no matching file is found, so using GCI first to test for a matching file.
if ($(Get-ChildItem $packageSourcePath\*.resw -Recurse).count -gt 0) {
xcopy $packageSourcePath\*.resw $objPath /s /i > $null
}
The condition using GCI is added to check there are matching files before calling xcopy, thereby avoiding any errors.
I'm still amazed that Copy-Item -Filter -Recurse didn't work.
This should do it (obviously this could be done in 1 line; I've assigned values to the variables just to help make it readable / self-explanatory):
[string]$filter = '*.resw'
[string]$source = Join-Path -Path $packageSourcePath -ChildPath '*'
[string]$target = $objPath
$source | Convert-Path | Copy-Item -Filter $filter -Recurse -Destination $target -Container #-Force
Notes:
We append the asterisk to the source path to ensure that we copy the contents of the source folder to the destination, without copying the source's root folder into the destination (i.e. say we're copying c:\temp\from to c:\temp\to, we don't want c:\temp\to\from (unless it's a copy of c:\temp\from\from)).
We use the Join-Path cmdlet to append this asterisk to ensure the appropriate slashes are inserted into the path.
We do a Convert-Path on the source to resolve the asterisk to the child folder/file names... for some reason copy-item doesn't handle these asterisks well. NB: Convert-Path will potentially return an array of paths; i.e. if there's more than one file/subfolder directly under the source folder. Get-Item or Resolve-Path could equally be used for this; I prefer Convert-Path since it returns a simple string array, rather than a more complex type; but there's no strong argument for using any one over the others.
We pipe these source paths to the Copy-Item command so it can be applied to each path returned by Convert-Path.
We include -Recurse to say we're interested in anything in the subfolders of the copied path.
We include the -Container parameter to say that we want to preserve any folder structure when copying. Strictly this is not needed, as this switch is defaulted to true (i.e. rather we should specify if we don't want this behaviour: -Container:$false; but I like to be clear that I deliberately want to preserve the directory structure, as opposed to leaving the assumption that I may not have thought of this. There's a better explanation of this here: https://stackoverflow.com/a/21798660/361842.
You could optionally include -Force; this would mean that should an item of the same name already exist in the target we overwrite it instead of getting an error.
Related documentation:
Join-Path
Convert-Path
Copy-Item
Update 2018-01-03
Per comments, this solution should ensure that only those items you want get copied, and pre-existing directories shouldn't cause issues.
[string]$filter = '*.resw'
[string]$source = $packageSourcePath
[string]$target = $objPath
#copy all files in subfolders of the source
$source | Get-ChildItem -Directory | Copy-Item -Filter $filter -Recurse -Destination $target -Container -Force
#copy all files in root of the source
$source | Get-ChildItem -File -Filter $filter | Copy-Item -Destination $target -Container -Force
This solution uses 2 steps; there's probably a better option, but due to the peculiarities / bug in this cmdlet the above's a reliable option.

Resources