copy and rename jpg files with PowerShell - powershell

I have the following structure:
mainfolder
folder1
000000.jpg
000001.jpg
000003.jpg
000004.jpg
folder2
000000.jpg
000001.jpg
folder3
000000.jpg
000001.jpg
000002.jpg
....
I want to copy and rename all the jpg-files. After the copying and renaming it should look like this:
mainfolder
folder1_000000.jpg
folder1_000001.jpg
folder1_000003.jpg
folder1_000004.jpg
folder2_000000.jpg
folder2_000001.jpg
folder3_000000.jpg
folder3_000001.jpg
folder3_000002.jpg
....
Can someone tell me how the PowerShell Skript for this looks like?

I would like to share the beautiful oneliner that lets you do this in PowerShell:
Get-ChildItem -Path mainfolder -Recurse -Filter "*.jpg" | % { $_ | Move-Item -Destination ("mainfolder\{0}_{1}" -f $_.Directory.Name, $_.Name) }

try this:
$DirRank=New-Object 'system.collections.generic.dictionary[string,int]'
$mainfolder="c:\temp"
Get-ChildItem $mainfolder -Recurse -File | %{
#Build or increment key for every sub-directory
if ($DirRank.ContainsKey($_.DirectoryName))
{
$DirRank[$_.DirectoryName]++
}
else
{
$DirRank[$_.DirectoryName]=0
}
#build new file name
$NewName="{0}\{1}_{2:d6}{3}" -f $mainfolder, $_.Directory.Name, $DirRank[$_.DirectoryName], $_.Extension
$fullename=$_.FullName
#rename and move item (remove -whatif for really rename)
move-Item $_.FullName $NewName -WhatIf -Force
}

Related

How to extract all zip files in subfolders in same folder using powershell

I have a nested folder structure for example like this (it's a lot more for simplicity I put an example)
- folder1
- folderA
a.zip
- folderB
b.zip
I want to unzip all zip files in same folder and delete the original zip file.
so my expected output is like
- folder1
- folderA
- a
files in a.zip
- folderB
- b
files in b.zip
I can get list of all zip files by Get-ChildItem '.' -R -Filter *.zip command
Then also I can pipe it to unzip like
Get-ChildItem '.' -R -Filter *.zip | Expand-Archive -Force -DestinationPath c:\a
which giving a fixed destination path
Also I can able to get the folder name of each zip file by
Get-ChildItem '.' -R -Filter *.zip | select -ExpandProperty DirectoryName
also I tried
Get-ChildItem '.' -R -Filter *.zip | Expand-Archive -Force -DestinationPath $_.DirectoryName
and
Get-ChildItem '.' -R -Filter *.zip | Expand-Archive -Force -DestinationPath %{$_.DirectoryName}
also
Get-ChildItem '.' -R -Filter *.zip | Expand-Archive -Force -DestinationPath {$_.DirectoryName}
But I can't find a way to pass the DirectoryName to Expand-Archive command
I found the solution in case someone else has same issue
Get-ChildItem '.' -R -Filter *.zip | ForEach-Object {
Expand-Archive $_.FullName "$($_.DirectoryName)/$($_.Basename)" -Force
Remove-Item $_.FullName
}
You can call the Directory property of the FileInfo objects outputted by Get-ChildItem to get the DirectoryInfo object of the parent folder of these files, then you can call the FullName property of the parents to get the destination folder.
In theory, this could work using -PipelineVariable instead of a ForEach-Object loop but I haven't personally tested it.
$ErrorActionPreference = 'Stop'
Get-ChildItem '.' -R -Filter *.zip | ForEach-Object {
try {
Expand-Archive -LiteralPath $_.FullName -DestinationPath $_.Directory.FullName -Force
Remove-Item -LiteralPath $_.FullName
}
catch {
Write-Warning $_.Exception.Message
}
}

Powershell: Extracting parts of file name to create folders and move files into the folder

I am a new starter to powershell and I am trying to achieve the following:
I have a list of files all in the same format: SURNAME_FIRSTNAME_CODE1_CODE2_NAME.pdf/docx etc
I want to create a subfolder named: SURNAME FIRSTNAME CODE1
and then move all of those relavant files into the folder.
I managed to find an article to do it with the first part (i.e SURNAME) but not really sure how to make it work with the others...any help would be greatly appreciated.
Here is what I have so far: (Thanks to a fellow poster for it)
Get-ChildItem -File -Path $directory -Filter "*.*" |
ForEach-Object {
New-Item -ItemType Directory "$directory$($_.Name.Split("_")[0])" -Force;
Move-Item -Path $_.FullName -Destination "$directory$($_.Name.Split("_")[0])\$($_.Name)"
}
This is how I'd do it. It uses Group-Object to group files that belong to the same directory, and the format operator to create the directory name. Let me know if you have any questions.
Get-ChildItem $directory -File |
group { "{0} {1} {2}" -f $_.BaseName.Split("_") } |
foreach {
$newDir = Join-Path $directory $_.Name
New-Item $newDir -ItemType Directory
$_.Group | Move-Item -Destination $newDir
}

Rename file by replacing character and overwrite

On Windows XP, in a folder of files, I need to rename some files, replacing one character in the filename with another and overwriting any files that already have that name.
For example, the folder contains these 2 files:
fileA.xml
fileb.xml
I need to rename fileA.xml to fileb.xml, overwriting the original fileb.xml
Using PowerShell, I have this command:
Get-ChildItem *.* -include *.xml | Rename-Item -NewName { $_.name.Replace("A","b")}
The rename doesn't work as the file already exists.
Doesn't have to be done in PowerShell, but this is the closest I've come so far.
You can try the Move-Item command instead, with the -Force parameter.
Get-ChildItem . -include *.xml | Move-Item -Destination { $_.name.Replace("A","b")} -Force
First, you need to filter to get the files that you actually want to rename.
Get-ChildItem . -include *.xml | Where-Object { $_.name -match "A$" }
And feed this to Move-Item to rename:
Get-ChildItem . -include *.xml | Where-Object { $_.name -match "A$" } | Move-Item -destination { $_.name -replace "A$", "b" }

rename a file if another file exists in Powershell

I have been looking for the way to do this using get-children and rename combined with if but no luck.
I want to search all subdirectories (subdir1, subdir2, etc) of a directory (test) for a file "trigger.txt" and if the file exists in one of these subdirectories I want to change the name of another file in the same subdirectory (changeme.txt to _changeme.txt)
Rephrasing:
If file subdir1\"trigger.txt" exists change subdir1\"changename.txt" to subdir1\"_changename.txt"
I have found scripts to change the name of file if it exists and to look for a file but I cannot connect it together... Any help?
Try this:
Get-ChildItem -r trigger.txt | Foreach {Rename-Item (Join-Path $_.DirectoryName changeme.txt) _changeme.txt}
And if you want the terse version:
ls -r trigger.txt | %{rni (join-path $_.DirectoryName changeme.txt) _changeme.txt}
Perhaps something like this?
ls -filter trigger.txt -recurse | %{
$original = Join-Path $(Split-Path $_.FullName -Parent) "ChangeMe.txt"
$newName = Join-Path $(Split-Path $_.FullName -Parent) "_ChangeMe.txt"
if ([IO.File]::Exists($original)) {
Write-Host "Renaming $($original)..."
ren -Path $original -NewName $newName
}
}

make copy of folder tree without files

I need to make copy of folder with subfolders, but do it without any files, except data that include folder "Project".
So I need to do new folders tree, but it should include only files that was present in subfolder named "Project".
ok, My solution:
$folder = dir D:\ -r
$folder
foreach ($f in $folder)
{
switch ($f.name)
{
"project"
{
Copy-Item -i *.* $f.FullName D:\test2
}
default
{
Copy-Item -exclude *.* $f.FullName D:\test2
}
}
}
Use xcopy /t to copy only the folder structure and then copy the Project folders separately. Something like this:
'test2\' | Out-File D:\exclude -Encoding ASCII
xcopy /t /exclude:d:\exclude D:\ D:\test2
gci -r -filter Project | ?{$_.PSIsContainer} | %{ copy -r $_.FullName d:\test2}
ri d:\exclude
Another solution:
$source = "c:\dev"
$destination = "c:\temp\copydev"
Get-ChildItem -Path $source -Recurse -Force |
Where-Object { $_.psIsContainer } |
ForEach-Object { $_.FullName -replace [regex]::Escape($source), $destination } |
ForEach-Object { $null = New-Item -ItemType Container -Path $_ -Force }
Get-ChildItem -Path $source -Recurse -Force |
Where-Object { -not $_.psIsContainer -and (Split-Path $_.PSParentPath -Leaf) -eq "Project"} |
Copy-Item -Force -Destination { $_.FullName -replace [regex]::Escape($source), $destination }
Use Get-ChildItem to recurse over folders and remap structure using New-Item. Within recursion, you can easily check for "Project".
First, create the directory structure:
xcopy D:\source D:\destination /t /e
Now, iterate through the source directory, copying every file in a Project directory:
Get-ChildItem D:\Source * -Recurse |
# filter out directories
Where-Object { -not $_.PsIsContainer } |
# grab files that are in Project directories
Where-Object { (Split-Path -Leaf (Split-Path -Parent $_.FullName)) -eq 'Project' } |
# copy the files from source to destination
Copy-Item -Destination ($_.FullName.Replace('D:\source', 'D:\destination'))