Powershell Move Files With Matching Substrings - powershell

I'm trying to clean up a directory with a ton of files with windows powershell, and so far all the other StackOverflow posts haven't seemed to help me crack my issue.
I have a parent directory named /1/
I have a sub directory named /1/j/
I want to have all of the files in directory /1/ with (J) in any part of their names (including the parenthesis) moved into the /j/ sub directory. Example filename would be: "example filename (J).smc"
Here is the code I have so far that's not working:
$source = 'F:\1\'
$destination = 'F:\1\j'
Get-ChildItem $source -filter *.smc -recurse | Select-String -List -Pattern "(J)" | ForEach-Object {
Move-Item $PSItem.Path -Destination $destination
}
I feel like it's something simple, so I apologize if it is! Thanks for your help!!!

Made it harder than it had to be. Thanks Olaf!
Solution:
Get-ChildItem -Path 'F:\1\' -Filter *'(j)'*.smc | Move-Item -Destination 'F:\1\j'

Related

Powershell move all files and subfolders in a child folder to CURRENT directory

I tried this, no error but no files have modved :
Get-ChildItem -Path "subfolder\" -Recurse | Move-Item -Destination "."
Update: I don't want ABSOLUTE but RELATIVE path
Your answer will be something like:
Move-Item -Path 'subfolder\*' -Destination . -Force
This is relative and will process all hidden files en folders as well.
Set-Location 'C:\Users\username\Desktop\newFolder';
Get-ChildItem -Path 'C:\Users\username\Desktop\oldFolder\*.txt' -Recurse -File | Move-Item -Destination $(get-location).Path;
This may seem like a crazy attempt and to be honest the question isn't as comprehensive as I'd like. For example: I'm not sure if the folder will only every be 1 level deep or could be further down from the current directory. At any rate, I got something that seems to be working basically by not bothering with recursion:
$SubFolder = 'YourFolderName'
$SubFolder = Get-Item .\$SubFolder
Get-ChildItem $SubFolder |
ForEach-Object{
$Destination = $_.FullName -Replace "$($SubFolder.FullName.Replace('\','\\'))", ".\"
$NewParent = $Destination -Replace $_.Name
Move-Item $_.FullName -Destination $NewParent
}
I think the trick here is you have to move to the parent's parent, etc or however many levels back/up. So figure out what the new parent should be using the current directory syntax .\. Once you have that you can move everything from the first level over not using recursion. Move-Item on a folder it knows to move the whole thing, and the files that are found in Sub-folder itself will obviously move to the new correct parent.
I had another working version that did use recursion, but this seems more concise and much to my surprise this seems to work. However, I'm not thrilled with it.

Powershell Loop through folder move file, create directory if doesn't exist

Good Afternoon,
I apologize if this is a basic question, but I have been struggling with it, also still very new to Powershell.
I have a network mapped folder Z:\Test.
Under Z:\Test is multiple subfolders with the same structure. I need to loop through all of the subfolders and move all PDF files if they exist in a specific location.
Z:\Test\1\Work\PDF\*.PDF - then move
Z:\Test\2\Work\PDF\*.PDF - Move So on and so on.
I have tried the following, but like I said I have been struggling with it. Thanks any help
Get-ChildItem -Path Z:\temp\*\Work -File -Include "*.PDF" -Recurse | Copy-Item -Force -Destination Y:\Temp\*\Work
I would try something like this:
$files = Get-ChildItem -Path Z:\Temp\*\Work -File -Include "*.PDF" -Recurse
foreach ($file in $files) {
Copy-Item -Path $file.FullName -Destination Y:\Temp\*\Work -Force
}

Powershell script to copy files based on filename

I have a folder that contains several thousand files. I would like to write a Powershell script that loops through the files and copies each file whose filename contains a specific keyword. In pseudocode:
For each file in C:\[Directory]
If filename contains "Presentation" Then
copy file in C:\[Directory 2]
Simply like this ?
copy-item "C:\SourceDir\*Presentation*" "C:\DestinationDir"
or like this :
copy-item "C:\SourceDir\*" "C:\DestinationDir" -Filter "*rrrr*"
But a risk exist if you have a directory with "presentation" in his name into the source directory. Then take all method proposed here and add -file in get-childitem command.
Like in this short version of Robdy code :
gci "C:\SourceDir" -file | ? Name -like "*Presentation*" | cpi -d "C:\DestinationDir"
That code should do the trick:
$files = Get-ChildItem -Path "C:\path\to\source\folder"
$files | Where-Object Name -Like "*Presentation*" | Copy-Item -Destination "C:\path\to\destination\folder"
Of course can be written in one line but I put in two for visibility.
Edit: as Esperento57 pointed out, you might want to add -ItemType File to Get-ChildItem cmdlet to not include folders with 'Presentation' in their name. Also, depending on your needs you might also want to use -Recurse param to include files in subfolders.
If you have files in subfolders and you want to keep the path in destination folder you'll have to change the script a bit to something like:
Copy-Item -Destination $_.FullName.Replace('C:\path\to\source\folder','C:\path\to\destination\folder')
And for the above you'll have to make sure that folders are actually created (e.g. by using -Force for Copy-Item.
This seems to work:
$src = "Dir1"
$dst = "Dir2"
Get-ChildItem $src -Filter "*Presentation*" -Recurse | % {
New-Item -Path $_.FullName.Replace($src,$dst) -ItemType File -Force
Copy-Item -Path $_.FullName -Destination $_.FullName.Replace($src,$dst) -Force
}
Try something like this:
Get-ChildItem "C:\Your\Directory" -File -Filter *YourKeyWordToIsolate* |
Foreach-Object { Copy-Item $_.FullName -Destination "C:\Your\New\Directory" }
... but, of course, you'll need to fill in some of the blanks left open by your pseudocode example.
Also, that's a one-liner, but I inserted a return carriage for easier readability.

XCOPY deployment script - how to include certain files?

I need to copy only certain parts of a folder using Powershell, specifically this list:
$files = #("MyProgram.exe",
"MyProgram.exe.config",
"MyProgram.pdb",
".\XmlConfig\*.xml")
In human readable form: 3 specific MyProgram.* files under root of target folder and all XML files under XmlConfig folder which itself is under root of source path (..\bin\Release\ in my case). XmlConfig folder must be created in destination, if it does not exist.
What I have tried:
(1) I tried the following, but it did not work, i.e. no folder or files were created at the destination path:
Copy-Item -Recurse -Path "..\bin\Release\" -Destination ".\Test\" -Include $files
(2) When -Include is removed, whole folder structure is successfully created, including subfolders and files:
Copy-Item -Recurse -Path "..\bin\Release\" -Destination ".\Test\"
It must be something wrong with my understanding of how -Include filter works:
(3) I tested an assumption that -Include needs an array of wildcards, but this did not work either:
$files = #("*MyProgram.exe*",
"*MyProgram.exe.config*",
"*MyProgram.pdb*",
"*.\XmlConfig\*.xml*")
Please advise on how to properly do Copy-Item in my case.
UPDATE (based on below answers):
I am looking for a generic implementation that takes an array of strings. It opens the possibility to put all necessary files/paths in one place, for easy editing, so that a non-Powershell knowledgeable person can understand and modify it as required. So in the end it would be single script to perform XCOPY deployments for any project, with input file being the only variable part. For above example, the input would look like this (saved as input.txt and passed as an argument to the main script):
MyProgram.exe
MyProgram.exe.config
MyProgram.pdb
.\XmlConfig\*.xml
I would prefer wildcards approach, since not many people know regex.
i don't know what is wrong with filter but you can still do
$files | % { copy-item ..\bin\release\$_ -Destination .\test}
if you want to preserve directoty structure you'll have to weak this a little, like :
$sourcedir="c:\temp\test"
$f=#("existing.txt","hf.csv";"..\dir2\*.txt")
$f |%{
$source=ls (join-Path $sourcedir $_) |select -expand directoryname
if ("$source" -like "$sourcedir*"){
$destination=$source.Substring($sourcedir.Length)+".\"
}
else{
$destination=$_
}
copy-item $sourcedir\$_ -Destination $destination -WhatIf
}
AFAICT -Include works only with file names or directory names and not combinations i.e. paths. You can try something like this:
$files = 'MyProgram\.exe|MyProgram\.exe\.config|MyProgram\.pdb|XmlConfig\\.*?\.xml'
Get-ChildItem ..\bin\release -r | Where {!$_.PSIsContainer -and ($_.FullName -match $files)} |
Copy-Item -Dest .\test
With wildcards you could do it this way:
$files = #('*MyProgram.exe','*MyProgram.exe.config','*MyProgram.pdb','*\XmkConfig\*.xml')
Get-ChildItem ..\bin\release -r |
Foreach {$fn=$_.Fullname;$_} |
Where {!$_.PSIsContainer -and ($files | Where {$fn -like $_})} |
Copy-Item -Dest .\test

Looking to find and copy files (with a specific file ext) from a Directory (recurse) using Powershell?

I am looking to Recurse a Folder Structure (ex.F:\Directory\layer1\layer2\layer3) and find all of the files with the specified file extension (ex. ".dll, .txt"). Then I need to copy the listed/found files to a destination folder.
If anyone could send me a good PowerScript that will do this I would much appreciate it.
I have a drive with about 1,000 folders and 5,000 files so this will probably save me a good day or two of manual work. :)
Thank You!
Try the following, modify as needed:
$movetopath = "C:\new folder\"
New-Item -Path $movetopath -ItemType Directory -Force
$files = Get-ChildItem -Path F:\ -Recurse
$files | Where-Object {$($_.Extension -eq ".dll") -or $($_.Extension -eq ".txt")} | ForEach-Object {Copy-Item $_ -Destination $movetopath}
I suggest you use find command first
then pipe the output of find command to tar.
Untar the archive to the destination folder.
Try something like
Get-ChildItem -Path $path -Recurse | where { !$_.PSIsContainer } | where { $_.Extension -eq ".txt" -or $_.Extension -eq ".log" } | Copy-Item -Destination $dest
This is propably slower then robocopy. Also, next time please show some effort and ask a question rather then a full solution. This is not a webshop.