I searched Stack Overflow and most of the answers I found, are not what I am trying to do. I have multiple files in the directory, that I am trying to rename by attaching the current date and time as a suffix before the extension.
I have done it multiple times on a single file, but cannot get it working for the bulk of files. Here is the code I am using:
Get-ChildItem $Path -Filter "*.dat" -Recurse | Rename-Item -NewName {$_.Basename + '_' + $curDateTime + $_.Extension }
It does not fail, but files are not renamed.
This works for me:
$curDateTime = Get-Date -Format yyyyMMdd-HHmmss
Get-ChildItem $Path *.dat -Recurse |
Rename-Item -NewName {$_.Basename + '_' + $curDateTime + $_.Extension } -WhatIf
Another solution:
Get-ChildItem $Path -Filter "*.dat" -Recurse |
ren -New {$_.Name -replace '[.](?!.*?[.])',"_${curDateTime}."} -What
Related
I'm new to PowerShell. Spent several days trying to get this, think I am very close, but need an expert to show me the final step.
Using PowerShell v5, Need to search for folder(s) which match specific name, then copy those folders and their files, AND the path to the Folders to another drive.
Script now:
Get-ChildItem s:\ -Filter (Read-Host -Prompt "Enter") -Recurse -ErrorAction SilentlyContinue -Force |
Select-Object FullName | ForEach-Object {Copy-Item -Path $_.FullName -Destination 'C:\Robotics\AA\ConfigFiles\Automation Anywhere Files\Automation Anywhere\My Tasks\' -recurse -Force}
This does a search for the Folder, returns results and then copies the folder and contents into the destination location.
The problem is, I actually needed the source path appended to my destination path. Source is variable number of folders deep.
Any suggestions?
To limit the Get-ChildItem to folders I inserted -Directory
Copy-Item accepts input from the pipeline, no ForEach-Object necessary.
the -replace is RegEx based and requires the backslash in the path
S:\ to be escaped by another backslash S:\\.
$DestBase = 'C:\Robotics\AA\ConfigFiles\Automation Anywhere Files\Automation Anywhere\My Tasks\'
$Search = Read-Host -Prompt "Enter folder:"
Get-ChildItem -Path S:\ -Filter $Search -Directory -Recurse -ErrorAction SilentlyContinue -Force |
Copy-Item -Destination {$($_.Fullname) -replace 'S:\\',"$DestBase"} -Recurse -Force -Whatif
If the output looks OK, remove the -WhatIf paramter in the last line.
I have a list of files say...
T123_Product_1.jpg
T123_Product_2.jpg
T123_Product_3.jpg
T456_Product_1.jpg
T456_Product_2.jpg
T456_Product_3.jpg
etc. etc. etc. for about 900 more files
What I am needing to do is create a folder based on the characters before the first underscore, but to not repeat it since there are multiple files.
So in the example above, I would only want two folders named T123 and T456.
Then I would need the script to place the appropriate files in the folder.
I had found some codes in this thread, but they don't exactly do what I'm looking for.
https://superuser.com/questions/306890/windows-batch-script-to-create-folder-for-each-file-in-a-directory-name-it-tha
$Files = Get-ChildItem -Path 'C:\Info\AUGUST 2011\Checklists\' -Filter 'DET1__*'
$Files | ForEach-Object {
$FileFullName = $_.FullName
$TempFileName = "$($FileFullName).tmp"
$DestinationFileName = "$FileFullName\$($_.Name)"
Move-Item $FileFullName $TempFileName
New-Item -Path $FileFullName -ItemType Directory
Move-Item $TempFileName $DestinationFileName
}
Any help?
The easiest way here would be to group the files by the first part, which will then become the directory name. In typical PowerShell pipeline manner this is fairly succinct:
Get-ChildItem -File | # Get files
Group-Object { $_.Name -replace '_.*' } | # Group by part before first underscore
ForEach-Object {
# Create directory
$dir = New-Item -Type Directory -Name $_.Name
# Move files there
$_.Group | Move-Item -Destination $dir
}
Also try.
cd <path to your folder>
$files = Get-ChildItem -file;
ForEach ($file in $files)
{
$folder = New-Item -type directory -name ($file.BaseName -replace "_.*");
Move-Item $file.FullName $folder.FullName;
}
You can use the Substring method on the $file.BaseName as well.
cd <path to your folder>
$files = Get-ChildItem -file;
ForEach ($file in $files)
{
$fileName = $file.BaseName;
$folder = New-Item -type directory -name $fileName.Substring(0, $fileName.Length-10);
Move-Item $file.FullName $folder.FullName;
}
The same posted here with explanation.
$directory="c:\temp\"
#explicit and long version
Get-ChildItem -File -Path $directory -Filter "*.jpg" |
ForEach-Object {
New-Item -ItemType Directory "$directory$($_.Name.Split("_")[0])" -Force;
Move-Item -Path $_.FullName -Destination "$directory$($_.Name.Split("_")[0])\$($_.Name)"
}
#short version
gci -File -Path $directory -Fi "*.jpg" |
%{ ni -ItemType Directory "$directory$($_.Name.Split("_")[0])" -Force;mvi $_.FullName "$directory$($_.Name.Split("_")[0])\$($_.Name)" }
I have a directory full of subdirectories that have any number of 0 to 300 files in them.
I want to output the subdirectory name and the number of files in that subdirectory
What I have so far is giving me 0 no matter how many actual files are in the subdirectory.
$dir = "C:\Folder\"
$subFiles = (Get-ChildItem $dir -recurse | where-object {$_.PSIsContainer -eq $true })
$subFiles | % {
Get-ChildItem -Path $_ -Force -Recurse | Measure-Object | Select-Object -ExpandProperty Count
write-host "$_"
}
Its also sometimes including the directories in which the script is being run ie "C:\Users\Blah\documents and settings\startmen" and causing errors.
Any help greatly appreciated thank you
You are using at least PowerShell 3.0 since you are using the -File parameter of Get-ChildItem so you dont need to use the where-object {$_.PSIsContainer -eq $true }. That has been replaced with the -Directory parameter. Loop through all the folders and collect the folder name and count of its files. I removed the -Recurse of the file count since that could be misleading. Put it back if it suits you better. The final Select-Object is to ensure the order of the output which is an object now that you could sort or do whatever you wanted with.
$dir = "C:\File"
Get-ChildItem $dir -Recurse -Directory | ForEach-Object{
[pscustomobject]#{
Folder = $_.FullName
Count = #(Get-ChildItem -Path $_.Fullname -File).Count
}
} | Select-Object Folder,Count
Insight
You were getting those errors before since you were not calling the full path in Get-ChildItem you were just calling the folder name. In the absence of a full path Get-ChildItem assumes you are looking for a folder in the current directory. That which is typically your user directory.
This method for count seems to be faster for remote directories.
$count = [System.IO.Directory]::GetFiles($_.Fullname).Count
This did exactly what I wanted :) Its not very pretty, but it worked..
$dir = "C:\folder\"
$subFiles = (Get-ChildItem $dir -recurse | where-object {$_.PSIsContainer -eq $true })
$subFiles | % {
$path = $dir+$_
$files = Get-ChildItem -Path $path -Force -Recurse -File -ErrorAction SilentlyContinue
write-host "$_ Files:" $files.count
}
I would like to use this option to delete those files with a specific extension (.cfg in my case) with different name of its folder. For example, if I have in a folder called MYFOLDER and inside this two files, MYFOLDER.cfg and otherfile.cfg, otherfile.cfg should be deleted (recursively).
That's all I have till now:
$folder = Get-ChildItem * -exclude *.* -name -recurse
$file = Get-ChildItem * -include *.cfg* -name -recurse | % { [IO.Path]::GetFileNameWithoutExtension($_) }
#$folder | ForEach-Object {Compare-Object $folder $file | <DELETE file with different name>}
How Could I make the last line?
Thanks in advance. Regards.
This will do it for you:
Get-ChildItem -Recurse -Include *.cfg | % { If ( $_.Name.Split(".")[0] -ne $_.Directory.Name ) {$_.Delete()}}
Two-Liner, but you can make it to a Single liner ;)
$FolderName = (Get-Location).Path.Split("\")[(Get-Location).Path.Split("\").Count -1]
$Files = Get-ChildItem | Where-Object {$_.Extension -ne ".cfg" -or $_.Name.Split(".")[0] -ne $FolderName} | Remove-Item -Recurse
But this Code and also the one from Musaab Al-Okaidi doesn't handle the case, when the Name of the file contains a dot (e.g. File.Name.cfg)
Remove -WhatIf to delete the files:
Get-ChildItem -Filter *.cfg -Recurse |
Where-Object {$_.BaseName -ne $_.Directory.Name} |
Remove-Item -WhatIf
I want to make a script which will take a parent directory which has a number of child directories which have files in them. Using a listing I wish to move all of the files in the child directories in to the parent directory.
I have created the following code so far which gives a listing of all the files of the specified type in the child directories but I am unsure how to a mass move of all the child files.
Write-host "Please enter source Dir:"
$sourceDir = read-host
Write-Host "Format to look for with . :"
$format = read-host
#Write-host "Please enter output Dir:"
#$outDir = read-host
$Dir = get-childitem -Path $sourceDir -Filter $format -recurse | format-table name
$files = $Dir | where {$_.extension -eq "$format"}
$files #| format-table name
A few things:
You can pass the text you write to the screen directly to the read-host cmdlet, it saves you a line per user input.
As a rule of thumb, if you plan to do more with an output of a command, DO NOT pipe it to the format-* cmdlets. The format cmdlets produces formatting objects that instructs powershell how to display the result on screen.
Try to avoid assigning the result to a variable, if the result contains a large set of file system, memory consumption can go very high and you can suffer a performance degradation.
Again, in terms of performance, try to use cmdlet parameters instead of the where-object cmdlet (server side filtering vs. client side). The first filters the objects on the target while the latter filters the objects only after the get to your machine.
The WhatIf switch will show you which files would have moved. Remove it to execute the command. You may also need to twick it to deal with duplicate file names.
$sourceDir = read-host "Please enter source Dir"
$format = read-host "Format to look for"
Get-ChildItem -Path $sourceDir -Filter $format -Recurse | Move-Item -Destination $sourceDir -Whatif
If I understood your question correctly, you can use Move-Item on files to move them to the output directory:
$Dir = get-childitem $sourceDir -recurse
$files = $Dir | where {$_.extension -eq "$format"}
$files | move-item -destination $outDir
A previous poster pointed out that the script would overwrite files of the same name. It might be possible to extend the script by a test and to avoid that possibility. Something like this:
$sourceDir = read-host "Please enter source Dir"
$format = read-host "Format to look for?"
$destDir = read-host "Please enter Destination Dir"
Get-ChildItem -Path $sourceDir -Filter $format -Recurse | Copy-Item -Destination $DestDir
$files = $DestDir | where {$_.extension -eq "$format"}
If (Test-Path $files) {
$i = 0
While (Test-Path $DestinationFile) {
$i += 1
$DestinationFile = "$files$i.$format"
Copy-Item -Destination $DestDir $DestinationFile
}
}
Else {
$DestinationFile = "$files$i.$format"
Copy-Item -Destination $DestDir $DestinationFile
}
Copy-Item -Path $SourceFile -Destination $DestinationFile -Force