I want to do to the following things:
do the listing of all the items in the directory
move the files according to their names into different location
Example: In my document folder I have various files. According to the file names, I will move them to different directory. I use the following script. But it is not working.
$allfiles = Get-ChildItem $home\documents
$count = 0
foreach($file in $allfiles)
{
if ($file.name -like "*Mama*")
{
move-item $file.name -Destination $home\documents\mom
$count++
}
elseif ($file.name -like "*Papa*")
{
move-item -destination $home\documents\Dad
$count++
}
elseif ($file.name -like "*bro")
{
Move-Item -Destination $home\documents\Brother
$count++
}
}
write-host "$count files been moved"
What I am doing wrong here?
My Error output is
move-item : Cannot find path 'C:\users\administrator\documents\Lecture3.txt' because it does not exist.
At line:6 char:10
{ move-item $file.name -Destination $home\documents\Win213SGG\lectures
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : ObjectNotFound: (C:\users\admini...ts\Lecture3.txt:String) [Move-Item], ItemNotFoundExceptio
n
FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.MoveItemCommand
move-item : Cannot find path 'C:\users\administrator\documents\Lecture3_revised.txt' because it does not exist.
At line:6 char:10
+ { move-item $file.name -Destination $home\documents\Win213SGG\lectures
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\users\admini...re3_revised.txt:String) [Move-Item], ItemNotFoundExceptio
n
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.MoveItemCommand
cmdlet Move-Item at command pipeline position 1
Supply values for the following parameters:
Path[0]:
Or you could make it even neater by using the pipe functionality in powershell. Like this, you don't have to specify with '-path' which file to move, but you can pass it on directly from the result of Get-ChildItem:
Get-ChildItem $home\documents | Foreach-Object {
$count = 0
if ($_.Name -like "*Mama*")
{
$_ | Move-Item -Destination $home\documents\mom
$count++
}
elseif ($_.Name -like "*Papa*")
{
$_ | Move-Item -Destination $home\documents\Dad
$count++
}
elseif ($_.Name -like "*bro")
{
$_ | Move-Item -Destination $home\documents\Brother
$count++
}
}
write-host "$count files been moved"
Try this -
$allfiles = Get-ChildItem $home\documents
$count = 0
foreach($file in $allfiles)
{
if ($file.name -like "*Mama*")
{
move-item -path $file -Destination $home\documents\mom
$count++
}
elseif ($file.name -like "*Papa*")
{
move-item -path $file -destination $home\documents\Dad
$count++
}
elseif ($file.name -like "*bro")
{
Move-Item -path $file -Destination $home\documents\Brother
$count++
}
}
write-host "$count files been moved"
You haven't specified the File Name at two occasions which is a mandatory parameter for move-item. And at one place you are trying to move the files using the Name parameter which is not an item(in literal sense). See if above works for you.
Related
I have to move files from a folder corresponding to a CSV column like that :
id
name
1a
file1
2b
file2
3c
file3
4d
file4
So if in my folder I have a file named file1 I need to create a folder named 1a and put file1 inside.
I have the following script
$CsvId = Import-Csv './test.csv'
$sourcePath= "C:\Users\olong\Desktop\object"
$dirPath = "C:\Users\olong\Desktop\dir"
$files = Get-ChildItem -Path $sourcePath | ForEach-Object -Process {[System.IO.Path]::GetFileNameWithoutExtension($_)}
$pattern = '(?<=_).*(?=_)'
ForEach ($item In $CsvId) {
$objectID = $item.'id'
$docID = $item.'name'
$location = $dirPath+ "\" + $objectID
Foreach ($file in $files) {
if($file -contains $docID) {
if (-not (Test-Path -Path $location)) {
mkdir -Path $location
}
Move-Item ($file.FullName) -Destination $location -Verbose -Force
}
}
}
But it gives me that error :
Move-Item : Cannot bind argument to parameter 'Path' because it is null.
At C:\Users\olong\Desktop\scriptMove.ps1:19 char:15
+ Move-Item ($file.FullName) -Destination $location -Verbose -Force
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Move-Item], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.MoveItemCommand
With PowerShell's debugger $file is not null and with or without parenthesis on $file.FullName does nothing
I think what you want to do is to get the file(s) as mentioned in the csv under header 'name' having any extension into a subfolder as mentioned in field 'id' and create that subfolder first if it does not already exist.
If my assumtion is correct, you can try below:
$sourcePath = "C:\Users\olong\Desktop\object"
$destinationPath = "C:\Users\olong\Desktop\dir"
Import-Csv -Path './test.csv' | ForEach-Object {
$targetDirectory = Join-Path -Path $destinationPath -ChildPath $_.id
# create the output subfolder if it does not already exist
$null = New-Item -Path $targetDirectory -ItemType Directory -Force
# next use the file basename from the $_.name column as filter and move the file(s)
Get-ChildItem -Path $sourcePath -Filter "$($_.name).*" -File | Move-Item -Destination $targetDirectory
}
EDIT: So after some research, since what I had wasn't quite doing the trick and the advice and comments from before got me further along than I was previously, I am back with a bit more research and a more complete script.
Import-CSV C:\saveme\file_path3.csv | ForEach-Object {
Get-ChildItem $_.path -Recurse | ForEach-Object {
$split = $_.FullName -split '\\'
$DestFile = $split[1..($split.Length - 1)] -join '\'
$DestFile = "G:\Recuva2\$DestFile"
$null = New-Item -Path $DestFile -Type File -Force
If (Test-Path $DestFile) {
$i = 0
While (Test-Path $DestFile) {
$i += 1
$DestFile = $DestFile+$i
}
} Else {
$null
}
Copy-Item -Path $_.FullName -Destination $DestFile -Verbose -Force
}
}
This seems to be breaking due to an inability to find the destination directory. It seems to be breaking on this line
$null = New-Item -Path $DestFile -Type File -Force
and this line
Copy-Item -Path $_.FullName -Destination $DestFile -Verbose -Force
The common denominator here seems to be the $DestFile. I understand I am doing a good bit to the $DestFile, but I can't seem to nail down what is causing it to break.
My desired end-result here is that the folder structure be maintained when copying the specific files over in the csv list from which I am importing.
What actually seems to be happening is that it is throwing errors whenever I attempt to copy. Error text below.
Copy-Item : Could not find a part of the path 'G:\Recuva2\HR_VIOLATORS\REPORTS\REPORT_Storage2\199452\1.3.6.1.4.1.11157.2011.3.21.8.12.5.52516\1.3.51.5156.1369.20110321.1190709\1.3.51.0.7.3750462839.61413.18976.39828.11247.2380.39394'.
At line:16 char:5
+ Copy-Item -Path $_.FullName -Destination $DestFile -Verbose -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], DirectoryNotFoundException
+ FullyQualifiedErrorId : System.IO.DirectoryNotFoundException,Microsoft.PowerShell.Commands.CopyItem
Command
-- END EDIT
ORIGNAL POST:
Similar to but not quite the same as
Keep rename duplicate items with copy
Essentially I am being forced to grab a list of directories from a csv file and copy their contents. However the problem I am having is that some of the directories and files are duplicated.
I am attempting to use this script to import from the csv, copy the files with directory structure intact, while renaming any duplicates, ideally at the file level so that the duplicate directories are merged.
Import-CSV C:\COPYME\file_path.csv | foreach($_.path) {
ls $_.path -recurse | foreach($_) {
$SourceFile = $_.FullName
$DestinationFile = "G:\Recuva2\"+$_
If (Test-Path $DestinationFile) {
$i = 0
While (Test-Path $DestinationFile) {
$i += 1
$DestinationFile = "G:\Recuva2\"+$_+$i
}
} Else {
New-Item -ItemType File -Path $DestinationFile -Force
}
Copy-Item -Path $SourceFile -Destination $DestinationFile -verbose -Force
}
}
I am receiving an error that says that line 2 character 24 cannot be resolved to a method? What am I missing/doing wrong here?
There is a difference between the ForEach-Object cmdlet and the ForEach loop.
Import-Csv -Path 'C:\COPYME\file_path.csv' |
ForEach-Object {
ls $_.path -recurse |
ForEach-Object {
$SourceFile = $_.FullName
$DestinationFile = "G:\Recuva2\"+$_
If (Test-Path $DestinationFile) {
$i = 0
While (Test-Path $DestinationFile) {
$i += 1
$DestinationFile = "G:\Recuva2\"+$_+$i
}
} Else {
New-Item -ItemType File -Path $DestinationFile -Force
}
Copy-Item -Path $SourceFile -Destination $DestinationFile -verbose -Force
}
}
With PowerShell 4.0+ there is a .foreach() method. But it looks like you are really trying to use the alias to ForEach-Object which as iRon has pointed out in the comments does not need the ($_).
Import-CSV C:\COPYME\file_path.csv | ForEach-Object {
Get-ChildItem $_.Path -Recurse | ForEach-Object {
$SourceFile = $_.FullName
$DestinationFile = "G:\Recuva2\" + $_
If (Test-Path $DestinationFile) {
$i = 0
While (Test-Path $DestinationFile) {
$i += 1
$DestinationFile = "G:\Recuva2\" + $_ + $i
}
} Else {
New-Item -ItemType File -Path $DestinationFile -Force
}
Copy-Item -Path $SourceFile -Destination $DestinationFile -Verbose -Force
}
}
As it turned out, I was causing my own problems by trying to pass data I had already gotten. A working version of the scripting is below. This worked flawlessly for every test I put it through thus far large and small. Thank you to the answers above for contributing to my knowledge and understanding of powershell.
Import-CSV C:\COPYME\file_path.csv | ForEach-Object {
Get-ChildItem $_.path -recurse | ForEach {
$split = $_.FullName -split '\\'
$DestinationFile = $split[1..($split.Length - 1)] -join '\'
$DestinationFile = "D:\HUBICOPY\$DestinationFile"
#$DestinationFile = (Resolve-Path $DestinationFile).Path
#$null = New-Item -Path $DestinationFile -Type File -Force
If (Test-Path $DestinationFile)
{
$i = 0
While (Test-Path $DestinationFile)
{
$i += 1
$DestinationFile = $DestinationFile+$i
}
}
Else {New-Item -ItemType File -Path $DestinationFile -Force}
Copy-Item -Path $_ -Destination $DestinationFile -verbose -Force
}
}
I'm having problems after a folder is copied to a different location, I need to rename the folders in the directory to remove ".deploy" from the end, but I get the following error below. I have Googled around for PowerShell admin permissions, but cannot seem to find a 'catch-all' for my scenario.
Get-Content : Access to the path 'C:\OldUserBackup\a.deploy' is denied.
At C:\PSScripts\DesktopSwap\TestMergeDir.ps1:28 char:14
+ (Get-Content $file.PSPath) |
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (C:\OldUserBackup\a.deploy:String) [Get-Content], UnauthorizedAccessException
+ FullyQualifiedErrorId : GetContentReaderUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetContentCommand
Here is what I have:
$UserName = [Environment]::UserName
$CurrUser = [Environment]::UserName + '.deploy'
$OldUserDir = 'C:\OldUserBackup'
$CurrDate = Get-Date -format G
$PathExist = Test-Path $OldUserDir
if ($PathExist -eq $true) {
#Copy Desktop, Downloads, Favorites, Documents, Music, Pictures, Videos
Copy-Item -Path $OldUserDir -Destination C:\Users\$UserName\Desktop\CopyTest -Recurse -Force
$configFiles = Get-ChildItem $OldUserDir *.deploy -rec
foreach ($file in $configFiles) {
(Get-Content $file.PSPath) |
Foreach-Object { $_ -replace ".deploy", "" } |
Set-Content $file.PSPath
}
}
You should use the -Directory switch on the Get-ChildItem cmdlet to only get directories. Then use the Rename-Item cmdlet to rename the folders. I use the -replace function with a simple regex to get the new folder name:
$deployFolders = Get-ChildItem $OldUserDir *.deploy -rec -Directory
$deployFolders | Foreach {
$_ | Rename-Item -NewName ($_.Name -replace ('\.deploy$') )
}
You don't even have to use the Foreach-Object cmdlet (Thanks to AnsgarWiechers):
Get-ChildItem $OldUserDir *.deploy -rec -Directory |
Rename-Item -NewName { $_.Name -replace ('\.deploy$') }
I want to remove bak files after zip from all subfolder for given path, so all duplicate files with extension .bak will be removed,i run below script but getting error.
$filePath = "d:\Test\"
$Afiles = Get-ChildItem -Recurse -Path $filePath | Where-Object {$_.Extension -eq ".bak"}
$Bfiles = Get-ChildItem -Recurse -Path $filePath | Where-Object {$_.Extension -eq ".7z"}
$Alist = #()
$Blist = #()
foreach( $A in $Afiles) {
$Alist += $A.baseName
}
foreach( $B in $Bfiles) {
$Blist += $B.baseName
}
foreach($A in $Alist) {
if($Blist -contains $a)
{
rm ("$A.bak")
}
}
I am receiving below error :
Remove-Item : Cannot find path 'C:\Users\******\Desktop\master_backup_2015_08_21_013722_8370267.bak' because it does not exist.
At C:\Users\*****\Desktop\duplicatedelete1.ps1:26 char:10
+ rm <<<< ("$A.bak")
+ CategoryInfo : ObjectNotFound: (C:\Users\****....722_8370267.bak:String) [Remove-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
You're receiving error because you're not specifying full path for rm command and PowerShell tries to delete file in your current directory.
Try this:
$Path = 'D:\Test'
Get-ChildItem -Path $Path -Recurse -Filter '*.7z' | ForEach-Object {
$BackupFile = Join-Path -Path (Split-Path $_.FullName -Parent) -ChildPath ($_.BaseName + '.bak')
if(Test-Path -Path $BackupFile){
Remove-Item -Path $BackupFile
}
}
I have this script where i want to move files from one path to another:
$logArchieveDirectory='C:\LogArchieve\'+$archiveTillDate.Day+$archiveTillDate.Month+$archiveTillDate.Year;
$sourcePathServer = 'C:\DDS\Server\LOGS';
$destPathServer=$logArchieveDirectory+'\Server';
#Create Directories
New-Item -ItemType directory -Path $logArchieveDirectory;
New-Item -ItemType directory -Path $destPathServer;
#Moving Logs to new temporary log archieve directories
foreach( $item in (Get-ChildItem $sourcePathServer | Where-Object { $_.CreationTime -le $archiveTillDate }) )
{
Move-Item $item $destPathServer -force;
}
However, i have specified both paths fine But i keep getting this error when i run this script.
Move-Item : Cannot find path 'C:\DDS\WorkFolder\WebAdapter' because it does not exist.
At C:\DDS\WorkFolder\powerShellScript08062014.ps1:38 char:11
+ Move-Item <<<< $item $destPathController;
+ CategoryInfo : ObjectNotFound: (C:\DDS\WorkFolder\WebAdapter:String) [Move-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.MoveItemCommand
The C:\DDS\WorkFolder\ is actually the folder where my script file is located. But what i am not understanding is why it is looking for the folder here and not where the path is given i.e. $sourcePathServer?
Your script passes relative paths to Move-Item and it defaults to the working directory. An easy solution is to pass absolute paths using .FullName property:
foreach ($item in (Get-ChildItem $sourcePathServer `
| Where-Object { $_.CreationTime -le $archiveTillDate })) {
Move-Item $item.FullName $destPathServer -force
}
Also using foreach in conjunction with pipelines doesn't look very elegant because of all the parentheses. You can get rid of it:
Get-ChildItem $sourcePathServer `
| Where-Object { $_.CreationTime -le $archiveTillDate } | Foreach-Object {
Move-Item $_.FullName $destPathServer -Force
}