One-line for zipping folder in PowerShell? - powershell

I'm looking for the equivalent PowerShell command for:
tar -zcvf tar-archive-name.tar.gz source-folder
Does such a one-liner exist that creates a zip file from a folder recursively adding the contents of the source-folder, that doesn't require a 3rd party library like 7-zip?

Starting with Powershell 5, you can use the built-in Compress-Archive command:
Compress-Archive -Path source-folder -DestinationPath archive-name.zip
If you are using powershell prior to version 5, there is no one liner solution without a third party program like 7-zip. However, you can leverage the built in zipping capabilities of windows explorer as exposed through the COM Shell object to build your own powershell function to do this. This page outlines the details on how to do so.

Actually, there is a one-line equivalent that creates zip archives, and there is even a one-liner to create an exact match, i.e. a tar file. The first place you should look for such a library function is PowerShell Community Extensions, providing a wealth of high-quality library extensions to PowerShell. Unfortunately, a web-search for a specific item, like your zip creation function, would likely not turn up anything because nowhere on the site or in the documentation do they include a list of the cmdlets and functions provided! To find out you have to install the library then do help about_pscx. Sifting through that, here is what you will find relevant to your question:
Write-Zip
Create ZIP format archive files from pipline or parameter input.
Write-GZip
Create GNU ZIP (GZIP) format files from pipeline or parameter input.
Write-Tar
Create Tape Archive (TAR) format files from pipeline or parameter input.
And here, from their embedded examples, are how you might use them:
PS> dir c:\logs\ -rec -inc *.log | write-zip -level 9 -removeoriginal
PS> dir c:\logs\ -rec -inc *.log | write-tar -output logs.tar | write-gzip -level 9 | move-item c:\archived_logs\

Related

Need windows batch command one-liner to remove folders by name, not by date.time using powershell if applicable

Need help with command like, one-liner, powershell to remove folders
I'm trying to find an elegant way to remove folders by folder name which reflects the date but I cannot rely on the file/folder date meta-data attributes.
Here's the problem I'm trying to solve:
I have a folder in which there are archived call recordings for each day the recording system creates folders and fills them with call recordings, a folder for each day named like format MM_dd_yyyy.
I need to remove all but the last 7 folders. But, I cannot rely on the creation/modified date on the file. That would be much easier with just powershell. So I MUST, unfortunately, remove the folders by testing the file name against the dates of the folders that I need to retain with same format (MM_dd_yyyy).
I can get the list of folder names that are to be retained base on the previous 6 days with the following Windows command line:
c:\>powershell $d0=(Get-Date).ToString('MM-dd-yyyy'); $d1=(Get-Date).AddDays(-1).ToString('MM-dd-yyyy'); $d2=(Get-Date).AddDays(-2).ToString('MM-dd-yyyy'); $d3=(Get-Date).AddDays(-3).ToString('MM-dd-yyyy'); $d4=(Get-Date).AddDays(-4).ToString('MM-dd-yyyy'); $d5=(Get-Date).AddDays(-5).ToString('MM-dd-yyyy'); $d6=(Get-Date).AddDays(-6).ToString('MM-dd-yyyy'); $d0; $d1; $d2; $d3; $d4; $d5; $d6
NOTE: I need to keep this in a command one-liner and cannot use PS1 power shell script because of corporate and domain enforced security limitations
This produces the folder names to be retained as listed below (ran on 20 NOV 2021 to retain last 7 days).
11_20_2021
11_19_2021
11_18_2021
11_17_2021
11_16_2021
11_15_2021
11_14_2021
The intention would be to remove any folder names that were like 11_13_2021, 11_12_2021... etc.
I can get away with running nested FOR loops in a Windows bat file to try and hack this together but I'm trying to find a more simple, readable and elegant one-liner that will let me do something like the following:
powershell $d=(Get-Date).AddDays(-7).ToString('MM-dd-yyyy'); and then some magic powershell stuff to remove any folder that doesn't match any of those that are to be retained.
If I had a way to provide the folder name (MM_dd_yyyy) to the (get-date).AddDays(-6) powershell command and have it return a boolean yes or no, that would be something closer to what I'm looking for.
I've been reading and you tubing and pulling hairs out but so far I'm learning but mostly making a mess of it. Any ideas are most welcome.
I'm likely approaching this all wrong. The constraints are:
Given a list of folders with naming format MM_dd_yyyy, I need to remove/delete all that are not within the last week of days.
I cannot run powershell scripts .ps1
I can run windows bat or cmd files with for loops and such
I cannot rely on the folder of files date/time meta attributes, some data in the folders may have create/write/modified dates that are not in line with the folder name. I must rely on the folder name (MM_dd_yyyy) to remove the folders.
UPDATED with resolution:
powershell "($f=Get-ChildItem -Path 'D:\PosConvSav' -Filter '*_*_*' -Directory | Where-Object { $_.Name -match '\d{2}_\d{2}_\d{4}' } | sort-object -desc)[14..($_.count)] | remove-item -recurse"
The PowerShell code for this would be:
Get-ChildItem -Path 'RootPath\Where\The\Folders\To\Delete\Are\Found' -Filter '*_*_*' -Directory |
Where-Object { $_.Name -match '\d{2}_\d{2}_\d{4}' } | # filter some more using regex -match
Sort-Object { [datetime]::ParseExact($_.Name, 'MM_dd_yyyy', $null) } | # sort by date
Select-Object -SkipLast 7 | # skip the newest 7 folders
Remove-Item -Recurse -Force # remove the rest
To play it safe, add -WhatIf to the final Remove-Item command. By doing that, the code does not actually delete anything, but show in the console what would be deleted. If you are satisfied that is correct, then remove -WhatIf to actually remove those folders.
As Olaf already commented, don't think using one-line code would be best, because what you'll end up with is code that isn't readable anymore and where mistakes are extremely hard to find.
There is no penalty whatsoever for multiline code, in fact it is THE way to go!

Enter individual folder(s) and execute PowerShell command

I have many folders with even more subfolders, and as posted in my first question
How to create a powershell script / or windows .bat file for ffmpeg
I want to encode all video files in the folders.
The Script I got from mklement0 works fine but lazy as I am, I was wondering if there was a way to tell the PowerShell to enter folder 1, go to subfolder_1, and execute the ps1 script (would be perfect if it executed in a new powershell instance), wait a certain time and go into subfolder_2
Repeat until no more subfolders available.
Is this possible?
Edit:
The Script I got:
Get-ChildItem *.mkv | where BaseName -notlike '*`[encoded]' | foreach {
ffmpeg -i $_ -c:v libx265 -c:a copy -x265-params crf=25 "$($_.BaseName)[encoded].mkv"
pause
}
What is the reason for the desire to process each subfolder in a separate instance of powershell.exe? by Mathias R. Jessen
Because I want to encode multiple folders at once to save some time.
If there is a way to execute the script in the same PowerShell (as far as my understanding goes, I can only encode one folder at one time if I use the same PowerShell instance)
You could wrap the whole thing in another Get-ChildItem to find all the subdirectories in your main folder, then set-location to that path and run in each of those:
$directories = get-childitem -path "C:\Path\To\Videos\Folder" -Recurse -Directory
Foreach ($dir in $directories) {
Set-Location $dir.fullname
*Run your code here*
}
This would be better than trying to do them all in parallel with different PowerShell instances. Correct me if I'm wrong, but video encoding uses a lot of your computer's resources, so trying to run them in parallel would actually be more of a hindrance.

Powershell: How to copy files from one Directory to another

I am looking to copy a series of files from one directory to another. Essentially the files are a series of zip folders that are simply changed versions of programs. The files will be named something like: test_1_092.zip in the source directory and test_1_091.zip in the target directory. I don't want the script to look at the numeric portion of the folder, simply the name.
Please forgive my lack of knowledge as this is my first foray into powershell scripting. Any thoughts or need more info?
Something to start with
(Get-ChildItem -Filter "*.zip").Name | where {$_ -like 'test_1_*'} | Move-Item -Destination .\1 -Force -WhatIf
Please confirm the output from –whatif , then remove it to perform the action.
For the relation between the new and old name, please provide some more information.

Can I use PowerShell `Expand-Archive` upon a zip file with no extension

I'm working upon a PowerShell script, where I have to extract the content out of a .zip archive which extension is removed, so, archive's name is let's say not test.zip but just test, and it is compressed as a .zip archive.
I'm trying to use for this purpose the PowerShell cmdlet Expand-Archive like shown below :
Expand-Archive -LiteralPath "Path to the archive" -DestinationPath "Extraction Path"
But, it doesn't seem to work, is there a possibility of extracting this archive's content with powershell, or it would be better to use a work around like 7zip command line tools, or something similar?
The Expand-Archive cmdlet is designed to explicitly work with a path that has a .zip extension. You can work around this by either creating a copy of your archive with a proper extension using Copy-Item or renaming the archive to have an extension with Rename-Item (using Move-Item may be more desirable if the archive with extension already exists and you want to overwrite it; Rename-Item is not capable of overwriting).

Recursive hard link

With Unix cp you can use the --link option. When used with a folder, it will
hard link the files involved instead of
copying, example
cp --recursive --link foo bar
This can be ideal in certain situations because it is faster than regular
copying. Can anything like this be done with PowerShell?
PowerShell doesn't have support for Symbolic/Hard Links currently. There are improvements on this front coming in PowerShell 5.0. The latest preview (September 2014) includes some of this functionality. You may want to peruse the release notes (docx):
To support symbolic links, *-Item and a few related cmdlets have been extended. Now you can create symbolic links in a single, simple line with New-Item.
An example:
New-Item -ItemType HardLink -Path C:\Temp -Name MyHardLinkFile.txt -Value $pshome\profile.ps1
There isn't an example for Copy-Item, but I assume it would be simple to use this with a recursive Get-ChildItem and pipe the results to New-Item, but you would have to try it yourself.
In the meantime, the PowerShell Community Extensions project has a New-Hardlink cmdlet. From the looks of it, you would have to do as I described above and pipe the results of Get-ChildItem into this cmdlet to create a hardlink for each file.