Copy directories when their name matches -Like txt files - powershell

I am trying to copy a bunch of directories. I have text files which have a similar name and I need to match the directories to those text files to determine which directories to copy.
This is what I have done and I can't figure out how to fix it. I am going around in circles.
$destination = "..\..\$args\Images\"
$txtfiles = Get-ChildItem $destination -Include *.txt
$source = "..\..\..\Images\" | ?{ $_.PSIsContainer } | Where-Object { $_.Name -Like "*$txtfiles*" } | Copy-Item $destination
An example of a txt file: 1e03655b-0aac-48b2-82f3-75942084af7a.txt
and folder: name.1e03655b-0aac-48b2-82f3-75942084af7a
So I need to find the folders that match the txt files and copy the folder to the txt file directory.
Thanks

You want to expand the BaseName properties of those text files (to cut off the .txt part) and have an array of strings such as:
1e03655b-0aac-48b2-82f3-75942084af7a
1e03655b-0aac-48b2-82f3-75942084af7b
1e03655b-0aac-48b2-82f3-75942084af8g
1e03655b-0aac-48b2-82f3-75942084afba
Then your $source = line needs to pull a directory listing and not just pipe a string down the pipeline, and then I would suggest matching the directory names with a regex match, and checking to see if that match is -in $txtfiles.
$destination = "..\..\$args\Images\"
$txtfiles = Get-ChildItem $destination -Filter *.txt | Select -ExpandProperty BaseName
$source = "..\..\..\Images\"
GCI $source -Directory | ?{ $_.Name -match "(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})$" } | %{If($Matches[1] -in $txtfiles){Copy-Item $_.FullName $destination}}

Related

Rename files in subfolders

I am trying to rename files in subfolders in a certain pattern, but I am stuck.
The situation is as follows: I have multiple folders which are sometimes named as the target filename depending on the length, but the name does not really matter.
In each folder are always 2 files: the Target-File with a random name and the correct extension, and the Source-File which is always the correct BaseName with a txt-extension.
For example:
Folder1\7393028473.docx
Folder1\January.txt
Folder2\9373930843.pdf
Folder2\February.txt
My goal is to rename every not-txt-file with the Basename of the txt-file. Executed, it should be like:
Folder1\January.docx
Folder1\January.txt
Folder2\February.pdf
Folder2\February.txt
With gci I was able to create both lists but didn't find a good way for the renaming.
$SourceName = gci -File -Recurse | Where {$_.Extension -ne ".txt"}
$TargetName = gci -File -Recurse | Where {$_.Extension -eq ".txt"}
I did also try to use gci for renaming, but was not able to tell it to use the newname based on the txt-file:
gci -File -Recurse | Where {$_.Extension -ne ".txt"} | Rename-Item -NewName {$_.extension -eq ".txt"}
This only renamed the .docx-file to "FALSE" because the filename already exists.
What I did not try (but would be ok) is to not only rename the file, but also move it to the parent directory.
This is one way to do it but it would fail as soon as there are 2 or more files with a different extension than .txt but having the same extension. It would also fail as soon as one folder has more than one .txt file.
# Get all folders under 'TargetDirectory'
Get-ChildItem TargetDirectory -Directory -Recurse | ForEach-Object {
# For each sub-folder, get their files
$childs = $_.EnumerateFiles()
# Filter and split the child files by their extension
$txt, $notTxt = $childs.Where({ $_.Extension -eq '.txt' }, 'Split')
# Use the BaseName of the '.txt' File but the Extension of
# the file being renamed
$notTxt | Rename-Item -NewName { $txt.BaseName + $_.Extension }
}
Thanks for your reply and sorry for my late reply.
I tried your code but its not working correctly:
The NewName is created correctly, but the problem is the rename-function or rather the notTxt list because it only contains the item itself but not hte full path.
When I copy the file which should be renamed into the parent-directory your code does work in the file in the parent-directory.
There was another answer which apperntly was deleted but did work.
I also tried a foreach-loop in one of my tries but didn't get the NewName to work.
I don't know why, but I didn't consider creating the NewName with a variable, which was done in the deleted answer:
$folders = gci -Directory -Recurse
foreach ($folder in $folders) {
$targetFile = gci $folder | Where {$_.Extension -ne ".txt"}
$sourceFile = gci $folder | Where {$_.Extension -eq ".txt"}
$newName = $sourceFile.BaseName + $targetFile.Extension
Rename-Item $targetFile.FullName $newName
}
Of course you can try and get your code to work, but I can make do with this code.
Thank you very much for your help.

Get ChildItem from only files of specific folders

I try to export files of specific named Folders:
Get-ChildItem -Path 'C:\Test' -Name -Recurse -File > C:\Test\Test.txt
I get a list like:
content.csv
Test.txt
Folder 1\INTERESTED_FOLDER\a - Kopie.txt
Folder 1\INTERESTED_FOLDER\a.txt
Folder 1\Neuer Ordner\ttt.txt
Folder 1\Neuer Ordner - Kopie\ttt.txt
Folder 2\INTERESTED_FOLDER\b - Kopie.txt
Folder 2\INTERESTED_FOLDER\b.txt
Folder 2\Neuer Ordner\ttt.txt
Folder 2\Neuer Ordner - Kopie\ttt.txt
But what i want is:
Folder 1\INTERESTED_FOLDER\a - Kopie.txt
Folder 1\INTERESTED_FOLDER\a.txt
Folder 2\INTERESTED_FOLDER\b - Kopie.txt
Folder 2\INTERESTED_FOLDER\b.txt
I tried with -Filter "INTERESTED" etc. but then i only get
C:\Test\Folder 1\INTERESTED_FOLDER
C:\Test\Folder 2\INTERESTED_FOLDER
What i do wrong?
If I read your question correctly, you want the FullNames of the files (so their names including the path).
If that is the case, remove the -Name switch and filter on the DirectoryName property like:
(Get-ChildItem -Path 'C:\Test' -Recurse -File |
Where-Object { $_.DirectoryName -match 'INTERESTED_FOLDER' }).FullName | # also matches 'MY_INTERESTED_FOLDER_123'
Set-Content -Path 'C:\Test\Test.txt'
Alternatives for the Where-Object clause:
# also matches 'MY_INTERESTED_FOLDER_123'
Where-Object { $_.DirectoryName -like '*INTERESTED_FOLDER*' }
or if you are looking for a precise match on the complete folder name
# does NOT match 'MY_INTERESTED_FOLDER_123'
Where-Object { $_.DirectoryName -split '[/\\]' -contains 'INTERESTED_FOLDER' }
You can perform a wildcard search using the -Filter parameter:
Get-ChildItem -Path 'C:\Test' -Name -Recurse -File -Filter *INTERESTED_FOLDER* > C:\Test\Test.txt
If for example, you were interested in finding the files in INTERESTED_FOLDER but also only the files that are .txt you could do:
-Filter *INTERESTED_FOLDER*.txt
Using the -Name parameter affects your capabilities because you are returning strings instead of FileInfoObjects. You may then use Where-Object to capture everything.
Get-ChildItem -Path 'C:\Test' -Name -Recurse -File |
Where {$_ -match '\\INTERESTED_FOLDER\\'} |
Set-Content c:\test\test.txt
Note that the matching above assumes INTERESTED_FOLDER is not a direct descendent of your path. If that is a possibility, then your match expression needs to be updated to \\?INTERESTED_FOLDER\\.

get-childitem find files in folders with same names

I need to check that all files in folders with the naming ".policy" is ether 'azureDeploy.parameters.json' or 'azureDeploy.json'
if i only want it to check one folder i just give the full path as here:
$azureDeployFiles = #('azureDeploy.parameters.json', 'azureDeploy.json')
(Get-ChildItem -path ..\..\fes\.policy -file -Recurse).name | Should -BeIn $azureDeployFiles
and that works. But i have multiple folders called something like '.\..\..\.policy' and i would like to check if all the folders with that naming only contains files with the naming 'azureDeploy.parameters.json' or 'azureDeploy.json'
You could specify 'only files in folders named X' with Where-Object on the Directory property:
$azureDeployFiles = #('azureDeploy.parameters.json', 'azureDeploy.json')
Get-ChildItem -path ..\..\ -Recurse -File |
Where Directory -Like "*\.policy" |
# example checking file names with -In
Foreach { $_.Name -In $azureDeployFiles }
Continuing from my comment. . .with a little help from the pipeline, we can use Where-Object to filter for directories with that specific name:
$azureDeployFiles = #('azureDeploy.parameters.json', 'azureDeploy.json')
Get-ChildItem -Path '.\MyPath' -Include $azureDeployFiles -Recurse |
Where-Object Directory -Like '*\.Policy'

Powershell copy directories and contents where name match with filter

I'm trying to use powershell to copy some directories where name match with filter.
First of all I delete all the directories that match in the destination path, alfter I try to copy source directories and contents but I've a problem because are copied only files inside directories and subdirectories and not the directories names and structures.
$source="F:\origin"
$destination="F:\dest"
$filter="#"
# Remove dirs #
Get-ChildItem -Path $destination -Recurse |
Where-Object { $_.DirectoryName -match $filter } |
remove-item -Recurse
# Copy dirs and all contents
Get-ChildItem -Path $source -Recurse |
Where-Object { $_.DirectoryName -match $filter } |
Copy-Item -Destination $destination
How can I do This ?
Thank you
EDIT
F:\origin\#test\index.php
F:\origin\#test1\index1.php
F:\origin\#test1\sub1\subindex1.php
F:\origin\no_consider\index1.php
Expected output
F:\dest\#test\index.php
F:\dest\#test1\index1.php
F:\dest\#test1\sub1\subindex1.php
a couple small tweaks seems to have done the trick. replaced some double quotes with single quotes, added a Recurse at the end of the one line and change DirectoryName to Name for the first one.
LEt me know if this works:
$source='c:\origin'
$destination='c:\dest'
$filter="#"
# Remove dirs #
Get-ChildItem -Path $destination -Recurse |
Where-Object { $_.Name -match $filter } |
remove-item -Recurse
# Copy dirs and all contents
Get-ChildItem -Path $source |
Where-Object { $_.Name -match $filter } |
Copy-Item -Destination $destination -Recurse -Force

Powershell : Match file name with folder name

I'm trying to match file name with folder name before move them to an other directory.
For example, my script need to match if "Test.txt" match with a folder named "Test" and move them to a different directory.
Is it possible with the cmdlets Get-ChildItem ? I didn't find any examples :(
Thanks a lot.
PowerShell 3+
Gets all files recursively from the current directory whose names (without extension) matches its directory's name:
Get-ChildItem -Path . -File -Recurse |
Where-Object { $_.BaseName -eq $_.Directory.Name }
PowerShell 1, 2
There is no -File switch until PowerShell 3, so you have to filter out directories with an extra Where-Object.
Get-ChildItem -Path . -Recurse |
Where-Object { -not $_.PsIsContainer } |
Where-Object { $_.BaseName -eq $_.Directory.Name }
Once you've got all the files that match their parent directory name, you should be able to move them. I'm not sure what your logic is for the destination directory structure.
For starters you can use the Directory property of Get-ChildItem
So lets say you are looking for a file test.txt but only if it is in the directory Scripts
Get-ChildItem *.txt -recurse | Where-Object{($_.Name -eq "test.txt") -and ($_.Directory -like "*\scripts")} | Move-Item $_.Directory "C:\NewFolder"
The Where clause will look for a file called text.txt as long as its in a folder called c:\somepath\scripts. So this will not match c:\anotherpath\test.txt. When a match is found Move the located files directory to a new location.
Note I am not sure if the logic will hold if multiple file matches are found. If it fails then we could assign all the matches to a variable and then process the all the unique values.
$foundDirectories = Get-ChildItem *.txt -recurse | Where-Object{($_.Name -eq "test.txt") -and ($_.Directory -like "*\scripts")} | Select-Object -ExpandProperty Directory -Unique
$foundDirectories | ForEach-Object{Move-Item $_ "C:\newfolder"}