Powershell: processing files in two folders based on what's in them - powershell

I have two directories: c:\Rar and c:\unRared
Rar - contains hundreds of RAR'ed files. Only one file inside the RAR. File inside the archive is with *.TRN extension.
UnRared has unarchived files (hundreds of files with *.TRN extension)
I've been trying to create a Powershell script to extract only files that have not been extracted already.

can't you just supply parameters to whatever compression program you have telling it not to overwrite existing files?

Knocked this out on my own...well, not really, with the help of developer
$dir1='C:\temp\aaa'
$dir2='C:\temp\bbb'
$CmdPath = "C:\Program Files (x86)\WinRAR\RAR.exe"
$Files2Extract = get-childitem -path 'C:\temp\aaa' -recurse -name -filter *.rar
#$d2 = get-childitem -path $dir2 -recurse
foreach($file in $Files2Extract){
$justname = $dir2+'\\'+(split-path $file -leaf).split(".")[0]+'.trn'
if(!(Test-Path -path $justname)) {
&$CmdPath e $file $dir2
}
}

Related

Using powershell archive individual files with winrar command line

I am struggling to archive file using PowerShell command with winrar
Folder has some text files N:\Download: abc.txt, xyz.txt
i would like to get output: N:\Download: abc.rar, xyz.rar and delete the text file after archive.
and how can I set the compressed level maximum?
https://documentation.help/WinRAR/HELPSwM.htm
here is my sample script
$Source = get-ChildItem -path N:\Download -filter "*.txt"
$Rarfile = "C:\Program Files\WinRAR\WinRAR.exe"
$Dest = "N:\Download"
&$WinRar a $Source.Fullname $Dest
From the documentation,
To delete the files after archiving, use the -df switch
To set the compression level use the -m<n> switch
Note, you have defined the full path to the winrar.exe file in variable $Rarfile, but later on you use undefined variable $WinRar..
If you want to create a .rar file for each source file separately, you will need a loop to be able to construct the output .rar filename
Try
$WinRar = "C:\Program Files\WinRAR\WinRAR.exe"
$Dest = "N:\Download"
(Get-ChildItem -Path 'N:\Download' -Filter '*.txt') | ForEach-Object {
$outFile = Join-Path -Path $Dest -ChildPath ('{0}.rar' -f $_.BaseName)
& $WinRar a -m4 -df $outFile $($_.Fullname)
# or use
# & $WinRar m -m4 $outFile $($_.Fullname)
}
If you do not want WinRar to include the folder structure of the files, append the -ep switch to the command

File System Searches and Files Moves with Powershell

I have a bit of a random task I have created for myself. I basically have a git repo in which there is a file structure and within a specific folder, I have several subfolders and nested in those folders are 3 config folders which have the same name. I am trying to create a powershell script thatll comb through the "Target Folder", copy the "Folder 1", "Folder 2", and "Folder 3", but only copy the contents of the 3 "Config Folder"s, maintaining that file structure, but only copying whats needed. Ideally, after that process, id love to rename these files with part of the name of the folder name to help differentiate. I do have plans to integrate a second part of the script to parse through those config files and export to an excel doc, but not sure how much I need that at the moment. The intended output is below, played around with a few misc file structure commands, but have not found much to help me achieve the below result.
File Structure:
Repo
TARGET FOLDER
DATA
FOLDER1
CONFIGFOLDER
MISC
FOLDER2
CONFIGFOLDER
MISC
FOLDER3
CONFIGFOLDER
ETC
Hoping to end up with
Export Folder
TARGET FOLDER
FOLDER1
CONFIGFOLDER
List of files with "FOLDER1_ogfilename.yaml"
FOLDER2
CONFIGFOLDER
List of files with "FOLDER2_ogfilename.yaml"
FOLDER3
CONFIGFOLDER
List of files with "FOLDER3_ogfilename.yaml"
I have created the following item to attempt this, and it copies the file structure, but it creates a folder for each .yaml file within that folder.
$sourceDir = "C:\Users\hhh\appdev\hhh\data\environments"
$targetDir = "C:\Users\hhh\appdev\targetfolder"
Get-ChildItem $sourceDir -Recurse | % {
$dest = $targetDir + $_.FullName.SubString($sourceDir.Length)
If (!($dest.Contains('research,qa,production,global')) -and !(Test-Path $dest))
{
mkdir $dest
}
Copy-Item $_.FullName -Destination $dest -Force
}
There are issues with your code.
you need to add switch -File to the Get-ChildItem cmdlet to have it look for files, not the directories inside $sourceDir
use Join-Path to construct your destination folder path. By adding the two strings together like you do, you will be missing a backslash
use the files DirectoryName property instead of its FullName when taking the substring from it, otherwise the $dest variable will also include the file name (creating folders for every file)
apparently you wish to not copy files from folders having certain keywords in their path name, so you need to put the copy command inside the test, not below it
Try:
$sourceDir = "C:\Users\hhh\appdev\hhh\data\environments"
$targetDir = "C:\Users\hhh\appdev\targetfolder"
Get-ChildItem $sourceDir -File -Recurse | ForEach-Object {
# use the files DirectoryName, not the FullName property, otherwise the path will include the file name as well
$dest = Join-Path -Path $targetDir -ChildPath $_.DirectoryName.SubString($sourceDir.Length)
# exclude paths containing these words
if ($dest -notmatch 'research|qa|production|global') {
# create the new folder if it does not already exist
$null = New-Item -Path $dest -ItemType Directory -Force
$_ | Copy-Item -Destination $dest -Force
}
}

Copy-Item with overwrite?

Here is a section of code from a larger script. The goal is to recurse through a source directory, then copy all the files it finds into a destination directory, sorted into subdirectories by file extension. It works great the first time I run it. If I run it again, instead of overwriting existing files, it fails with this error on each file that already exists in the destination:
Copy-Item : Cannot overwrite the item with itself
I try, whenever possible, to write scripts that are idempotent but I havn't been able to figure this one out. I would prefer not to add a timestamp to the destination file's name; I'd hate to end up with thirty versions of the exact same file. Is there a way to do this without extra logic to check for a file's existance and delete it if it's already there?
## Parameters for source and destination directories.
$Source = "C:\Temp"
$Destination = "C:\Temp\Sorted"
# Build list of files to sort.
$Files = Get-ChildItem -Path $Source -Recurse | Where-Object { !$_.PSIsContainer }
# Copy the files in the list to destination folder, sorted in subfolders by extension.
foreach ($File in $Files) {
$Extension = $File.Extension.Replace(".","")
$ExtDestDir = "$Destination\$Extension"
# Check to see if the folder exists, if not create it
$Exists = Test-Path $ExtDestDir
if (!$Exists) {
# Create the directory because it doesn't exist
New-Item -Path $ExtDestDir -ItemType "Directory" | Out-Null
}
# Copy the file
Write-Host "Copying $File to $ExtDestDir"
Copy-Item -Path $File.FullName -Destination $ExtDestDir -Force
}
$Source = "C:\Temp"
$Destination = "C:\Temp\Sorted"
You are trying to copy files from a source directory to a sub directory of that source directory. The first time it works because that directory is empty. The second time it doesn't because you are enumerating files of that sub directory too and thus attempt to copy files over themselves.
If you really need to copy the files into a sub directory of the source directory, you have to exclude the destination directory from enumeration like this:
$Files = Get-ChildItem -Path $Source -Directory |
Where-Object { $_.FullName -ne $Destination } |
Get-ChildItem -File -Recurse
Using a second Get-ChildItem call at the beginning, which only enumerates first-level directories, is much faster than filtering the output of the Get-ChildItem -Recurse call, which would needlessly process each file of the destination directory.

Powershell Get-ChildItem -recurse doesn't get all items

I'm working on a powershell script erase certain files from a folder, and move the rest into predefined subfolders.
My structure looks like this
Main
(Contains a bunch of pdb and dll files)
-- _publish
--Website
(Contains a web.config, two other .config files and a global.asax file)
-- bin
(Contains a pdb and dll file)
-- JS
-- Pages
-- Resources
I want to remove all pdb, config and asax files from the entire file structure before I start moving them. To which I use:
$pdbfiles = Get-ChildItem "$executingScriptDirectory\*.pdb" -recurse
foreach ($file in $pdbfiles) {
Remove-Item $file
}
And so on for all filetypes I need removed. It works great except for a pdb file located in the bin folder of the website. And for the ASAX file in the website folder. For some reason they get ignored by the Get-ChildItem recurse search.
Is this caused by the depth of the items within the resursive structure? Or is it something else? How can I fix it, so it removes ALL files as specified.
EDIT: I have tried adding -force - But it changed nothing
ANSWER: The following worked:
$include = #("*.asax","*.pdb","*.config")
$removefiles = Get-ChildItem "$executingScriptDirectory\*" -recurse -force -include $include
foreach ($file in $removefiles) {
if ($file.Name -ne "Web.config") {
Remove-Item $file
}
}
Get-ChildItem -path <yourpath> -recurse -Include *.pdb
You can also use the pipe for remove:
Get-ChildItem -path <yourpath> -recurse -Include *.pdb | rm

Powershell - copy files to different destination folders based on file names

Dear Powershell Gurus,
I have a few thousands of files in a folder called C:\Downloads\Signs.
The files are named with their dimensions such as 13X20 abcdjd.psf, 8X20 jdscnjfc.psf, 14X24 dje.psf etc.
What I want to do is to move these files to destination folders created within the C:\Downloads\Signs and the folder names are the dimensions of the file names. Example the folder names will be 13X20, 8X20, 14X24 etc and it depends upon as many unique file names with their dimensions.
So, instead of moving them manually looking at how many files are there in the C:\Downloads\Signs folder and then moving them individually, how can we do it in Powershell?
Thanks,
Sanders.
This script will pick up all psf from the root of the C:\Downloads\Signs folder and will move the files to the destination folders (folders will create if they do not exist):
Get-ChildItem C:\Downloads\Signs -Filter *.psf | Where-Object {!$_.PSIsContainer} | Foreach-Object{
$dest = Join-Path $_.DirectoryName $_.BaseName.Split()[0]
if(!(Test-Path -Path $dest -PathType Container))
{
$null = md $dest
}
$_ | Move-Item -Destination $dest -Force
}