Hello everyone,

I have a small problem with my process, so i have structure folders like these below (it’s example describe):
Folder1
Input
Output
1.txt

Folder2
Input
Output
2.txt
I wanna to move only txt files to output folders, these main Folders like Folder1, Folder2 will be a lot of more in the future and their name will be not like Folder1, Folder2.

Very important things in this process is move file .txt to Output folder with no overwrite.
I have created script/alghoritm that move these files in the loop but this process it’s wrong because this process see only name Folder1, Folder2.
Do you know any way to solve my problem.
Thank you for the answer

12 Spice ups

Please post the code you have tried and we’ll try to helpIf you post code, please use the ‘Insert Code’ button. Please and thank you!

192033ab-bb8f-4032-88a5-8e2313af0344-codebutton_small.png

I wanna to improve my above structure Folder, i forgot add to hierarchy Main_folder, Correct Hierrarchy looks like below:

Main_Folder

Folder1

Input

Output

1.txt

Folder2

Input

Output

2.txt

My script looks like below:

$RootFolder = "C:\Main_Folder\"

$SubFolders = Get-ChildItem -Path $RootFolder -Directory

$DestinationDirectory = 'C:\Main_Folder\*\*\Output'
Foreach($SubFolder in $SubFolders)
{ Get-ChildItem -Path $SubFolder -Filter '*.txt' -File -Recurse|
where {(Get-Content $_.FullName) -match $TextToFind} |
    Move-Item -Destination $DestinationDirectory }

For clarification, if the Output folder supposed to be C:\Main_Folder\Folder1\Output or C:\Main_Folder\Folder1\Input\Output? The folder structure in your initial question suggests the first, but the structure of $DestinationDirectory with **\Output implies the second.

My thought would be to drop the $DestinationDirectory variable, and change the end of the code to Move-Item -Destination " C:\Main_Folder$SubFolder\Output" as an example. You would need the sub folder data to determine the correct location as far as I know.

I admit to not being an expert, but this does look to me like it should work.

Where are the files coming from ?? Why not edit the process such that the output throws the files of the correct type into the correct respective folders ??

Else you have to run a schedule task every hourly (for example) and “move d:\output*.txt d:\1_txt” (please refrain from using dots within file names or folder names)

Thank you everyone for the answer, @smalltownitguy my second hierarchy is correct, @adrian_ych my process is subprocess in project, i wanna to show you my new code after answer above:

$RootFolder ="C:\Main_Folder" 
 $SubFolders = Get-ChildItem -Path $RootFolder -Directory
 Foreach($SubFolder in $SubFolders){ 
 Get-ChildItem -Path $SubFolder -Recurse -Directory -Filter '*.txt' -File| 
 Move-Item -Destination "C:\Main_Folder\$SubFolder\Output" }

But this code is not working dont move txt files. After run it this process nothing make.

$RootFolder ="C:\Main_Folder" 
$SubFolders = Get-ChildItem -Path $RootFolder -Directory
Foreach($SubFolder in $SubFolders){ 
    Move-Item -Path $RootFolder\$Subfolder\*.txt -Destination $RootFolder\$SubFolder\Output\
}

After some time to think on it (and a good night’s sleep), I looked at it again. I came up with the above code, and in a test I ran it did work.

Thats where things go wrong as the project should already have the output to different folders already ??

Then it is a simple move command… or robocopy /move … no need for each etc ??

It works thank you !!! :), do you know Maybe how to move this File with no overwrite? Im using force but in the future i will be must move File with no overwrite.

What is unlike -Force in powershell ?

With the code I provided it will fail if the file already exists. If you are looking to have it rename the file as it is moving if there is an existing file, then I would think it would need an if statement in the foreach loop, and quite a bit more work.

$RootFolder = "C:\Main_Folder"
$SubFolders = Get-ChildItem -Path $RootFolder -Directory
ForEach($SubFolder in $SubFolders){ 
    $Files = Get-ChildItem -Path $RootFolder\$SubFolder\ -Name *.txt
    ForEach($File in $Files) {
        If (!(Test-Path -Path $RootFolder\$SubFolder\Output\$File -PathType Leaf)){
            Move-Item -Path $RootFolder\$SubFolder\$File -Destination $RootFolder\$SubFolder\Output\$File
            }
        Else {
            Move-Item -Path $RootFolder\$SubFolder\$File -Destination "$RootFolder\$SubFolder\Output\$(get-date -Format 'MMM-dd-yyyy_hh-mm-ss')_$File"
            Start-Sleep -Seconds 2
            }
        }
}

OK, came up with an updated script that will evaluate it. If the file does not exist in the destination it will move it, if it does already exist it will add the date and time to the beginning of the filename. I also put a delay of two seconds if it detects a duplicate, this is so that it will still have a unique name if multiple files qualify (I know this shouldn’t happen as that means you have duplicates in the starting folder, but one extra line of code to avoid issues is nothing).

Is this a project or some actual work ??

Coz if this is a real-life production reporting server and someone somehow created like an hourly sales report but output PDF, txt, xls and /or docs into a single folder…I would really not consider using “move” in case of some error and files goes missing.

@echo off
start xcopy d:\output\*.txt d:\txt /y /d
start xcopy d:\output\*.xls? d:\xls /y /d
start xcopy d:\output\*.doc? d:\doc /y /d
start xcopy d:\output\*.pdf d:\pdf /y /d

Then you can do housekeeping on d:\output as required.

You can also create the above into a batch file and put into task scheduler

Looking at your script…what will happen if there is no file of that type in d:\output ?? Will it cause the script to stop running ? Thats why for the batch I use “start” so that any errors will not cause the batch file to stop.

I am not saying PS is not good…but sometimes keeping things as simple and straightforward is best ?

1 Spice up

I just force the rename.

##  Keep old file by renaming it to unique name
Rename-Item ".\$ScriptName.csv" ".\$ScriptName($(Get-Date -format yyyy-MM-ddTHH-mm-ss)).csv" -Force -ErrorAction SilentlyContinue
##  Emit the results file
$Results | Set-Content -Path ".\$ScriptName.csv"

If it fails, that’s because the file did not exist, hence the -ErrorAction SilentlyContinue.