Move the folder that does not contain inside a specific folder name

English support forum

Moderators: Hacker, petermad, Stefan2, white

Post Reply
pphktvmd
Junior Member
Junior Member
Posts: 2
Joined: 2024-12-13, 10:35 UTC

Move the folder that does not contain inside a specific folder name

Post by *pphktvmd »

Hello, I have over 1 TB of files to transfer.

What is the easiest way to solve this problem?
I would like to move project folders that do not contain a folder named PRINT inside.
I would also like to keep the folder structure: BRAND/PROJECT NAME

Folder structure explanation below:
Image: https://i.imgur.com/jqh4NwX.jpeg
User avatar
Dalai
Power Member
Power Member
Posts: 9943
Joined: 2005-01-28, 22:17 UTC
Location: Meiningen (Südthüringen)

Re: Move the folder that does not contain inside a specific folder name

Post by *Dalai »

If I understood it correctly it should be easy to achieve. In the copy/move dialog enter this into the field "Only files of this type":

Code: Select all

*.* | print\
This excludes every directory named "print" regardless of where it appears.
#101164 Personal licence
Ryzen 5 2600, 16 GiB RAM, ASUS Prime X370-A, Win7 x64

Plugins: Services2, Startups, CertificateInfo, SignatureInfo, LineBreakInfo - Download-Mirror
User avatar
white
Power Member
Power Member
Posts: 5744
Joined: 2003-11-19, 08:16 UTC
Location: Netherlands

Re: Move the folder that does not contain inside a specific folder name

Post by *white »

Dalai wrote: 2024-12-13, 12:38 UTC This excludes every directory named "print" regardless of where it appears.
That's not what he wants. He want to move all <brand>\<project> folders that do not contain a <brand>\<project>\PRINT folder. And he wants to retain the <brand>\<project> folder structure.

Probably the easiest way is to use a script of some kind. For example a batch file like this:

Code: Select all

@echo off
setlocal

set "sourceFolder=c:\test\MAIN_DIRECTORY"
set "destFolder=d:\test\MAIN_DIRECTORY"

for /d %%b in ("%sourceFolder%\*") do (
  :: %%b holds the name of the current brand folder
  for /d %%p in ("%%b\*") do (
    :: %%p holds the name of the current project folder
    if not exist "%%p\PRINT" (
      echo Moving "%%p" to "%destFolder%\%%~nxb\%%~nxp"
      robocopy "%%p" "%destFolder%\%%~nxb\%%~nxp" /E /MOVE /NFL /NDL /NJH /NJS
    )
  )
)

endlocal
pause
Fla$her
Power Member
Power Member
Posts: 2982
Joined: 2020-01-18, 04:03 UTC

Re: Move the folder that does not contain inside a specific folder name

Post by *Fla$her »

Button code:

Code: Select all

TOTALCMD#BAR#DATA
%ComSpec% /q/c for /d %d in (*) do for /d %p in ("%~fd\*") do if not exist "%~fp\print\" >nul robocopy "%~fp"
"%T%%d\%%~nxp" /move /e /ndl /nfl /njh /njs
wcmicon2.dll,50
Move *\<subfolders> where there is no *\<subfolder>\print\ to the target panel

1
Overquoting is evil! 👎
User avatar
beb
Power Member
Power Member
Posts: 579
Joined: 2009-09-20, 08:03 UTC
Location: Odesa, Ukraine

Re: Move the folder that does not contain inside a specific folder name

Post by *beb »

PowerShell-based solution:

Code: Select all

$oldLocation = 'x:\oldLocation\BRAND\PROJECT NAME'
$newLocation = 'y:\newLocation\BRAND\PROJECT NAME'

Get-ChildItem  $oldLocation -recurse -force -file | Where {($_.FullName.Split('\')) -NotContains 'print'} | foreach {
$destination = $newLocation + $_.FullName.SubString($oldLocation.Length) 
if (-not ($destination|Test-Path)) {New-Item -type file -path $destination -force}
Move-Item $_.FullName -destination $destination -force}
What it does:
Moves content of 'BRAND\PROJECT NAME' from the $oldLocation to the $newLocation wherever its path does not contain any subfolder named 'print', and preserves original directories structure.
#278521 User License
Total Commander [always the latest version, including betas] x86/x64 on Win10 x64/Android 10/15
User avatar
beb
Power Member
Power Member
Posts: 579
Joined: 2009-09-20, 08:03 UTC
Location: Odesa, Ukraine

Re: Move the folder that does not contain inside a specific folder name

Post by *beb »

Note.
The above solutions have a drawback: all the folders' special attributes will be lost.
This is a regular robocopy behavior (see https://ghisler.ch/board/viewtopic.php?p=423718#p423718).
The initial PowerShell script was made without keeping this in mind, too.
However, sometimes it matters.

So here's an update:

PowerShell-based solution v2:
What it does:
Moves contents of 'BRAND\PROJECT NAME' from the $oldLocation to the $newLocation wherever its path does not contain any subfolder named 'print', preserving both the original directories structure and the original folders' attributes.
All data behind 'print' subfolders are being kept intact in the original location.

Code: Select all

$oldLocation = 'x:\oldLocation\BRAND\PROJECT NAME' # put here path to the actual 'old' contents location root
$newLocation = 'y:\newLocation\BRAND\PROJECT NAME' # put here path to the desired 'new' contents location root

# !!! the below line is for testing purposes only : otherwise remove or comment it 
. $PSScriptRoot\moveItem_MovePathTest_tempEnvironment.ps1
# ^^^ the above line is for testing purposes only : otherwise remove or comment it 

# defining required source contents excluding paths that contain a sub-folder named 'print'
Get-ChildItem  $oldLocation -recurse -force | Where {$_.FullName.Split('\') -NotContains 'print'} | foreach {
# defining source path depending on whether a file or a folder is being piped
if ($_ -is [IO.DirectoryInfo]) {$source = [IO.DirectoryInfo]($_.FullName)}
if ($_ -is [IO.FileInfo])      {$source = [IO.DirectoryInfo]($_.DirectoryName)}
# defining destination path
[IO.DirectoryInfo]$destination = $newLocation + $source.toString().SubString($oldLocation.Length)
# making destination folder if it did not exist, and restoring original folder attributes
if (-not ($destination|Test-Path)) {New-Item -path $destination -type directory -force | Out-Null
$destination.Attributes = $source.Attributes}
$source      | Write-Host -f Yellow
$destination | Write-Host -f DarkCyan
# moving contents to new location
$path = $source.toString()+'\*'
Move-Item -path $path -destination $destination -force # -verbose # -whatIf
''
}

# clean-up: remove empty folders that Move-Item might left behind in $oldLocation
Get-ChildItem $oldLocation -force -recurse -EA Silent|Where {$_.PSIsContainer -and @(Get-ChildItem -literal $_.FullName -force -recurse -EA Silent|Where {!$_.PSIsContainer}).Length -eq 0}|Remove-Item -force -recurse -EA Silent
moveItem_MovePathTest_tempEnvironment.ps1 child script for testing (if needed)

Code: Select all

# This script is to quickly create a minimally sufficient testing environment within the user's temporary directory ($env:Temp) to see how the main script works

$oldLocation = 'x:\oldLocation\BRAND\PROJECT NAME'
$newLocation = 'y:\newLocation\BRAND\PROJECT NAME'

$tempArea    = [IO.Path]::combine($env:Temp,'moveItem')
$oldLocation = $oldLocation.Replace('x:',$tempArea)
$newLocation = $newLocation.Replace('y:',$tempArea)

$file  = $oldLocation+'\notprint\notprint_file.txt';if (!($file|Test-Path)) {New-Item $file -type file -force -value $file > $null}
$file  = $oldLocation+'\preprint\preprint_file.txt';if (!($file|Test-Path)) {New-Item $file -type file -force -value $file > $null}
$file  = $oldLocation+'\print\print_file.txt';      if (!($file|Test-Path)) {New-Item $file -type file -force -value $file > $null}
$hereString  = @"
[.ShellClassInfo]
IconResource=%SystemRoot%\system32\shell32.dll,122

"@
$file  = $oldLocation+'\readOnly\desktop.ini'
if (!($file|Test-Path)){
New-Item $file -type file -force -value $hereString > $null
attrib   ($file|Split-Path -parent) +r /d > $null
}

$cleanup    = $tempArea+'\newLocation'
if (Test-Path $cleanup) {
Get-ChildItem $cleanup -recurse -force|Remove-Item -recurse -force -EA:Silent
Remove-Item   $cleanup -recurse -force -EA:Silent}
#278521 User License
Total Commander [always the latest version, including betas] x86/x64 on Win10 x64/Android 10/15
Fla$her
Power Member
Power Member
Posts: 2982
Joined: 2020-01-18, 04:03 UTC

Re: Move the folder that does not contain inside a specific folder name

Post by *Fla$her »

beb wrote: 2024-12-14, 16:09 UTCThe above solutions have a drawback
Different solutions from mine have another equally important drawback - they are not directly related to TC and, as a result, to this forum. :)
Overquoting is evil! 👎
User avatar
beb
Power Member
Power Member
Posts: 579
Joined: 2009-09-20, 08:03 UTC
Location: Odesa, Ukraine

Re: Move the folder that does not contain inside a specific folder name

Post by *beb »

2Fla$her
I believe this is not the way this board works.
Respecting the specifics of the use case requested here, I don't think a user would perform the operation on an everyday basis.
It's rather a kind of a yearly task if not a once-in-lifetime one.
Therefore, from my point of view, it's much safer for a user to use a standalone script to move a terabyte of data here and there.
Otherwise, that's not a big deal to wrap such a solution as, for example, my PowerShell script, into a TotalCommander interface.

Adapted PowerShell script:
moveProject_butPrint.ps1

Code: Select all

# when running this script standalone:
# put here the literal locations required for the standalone script use
$oldLocation = 'x:\oldLocation\BRAND\PROJECT NAME' # root path to the actual 'old' contents location
$newLocation = 'y:\newLocation\BRAND\PROJECT NAME' # root path to the desired 'new' contents location

# when running this script within a TotalCommander command:
# the locations would be defined from the %P %T parameters passed to the script by TotalCommander
if ($args){
$oldLocation = $args[0]
$newLocation = $args[1]
$oldLocation = $oldLocation.substring(0,$oldLocation.length -1)
$newLocation = $newLocation.substring(0,$newLocation.length -1)}

# defining required source contents excluding paths that contain a sub-folder named 'print'
Get-ChildItem  $oldLocation -recurse -force -file| Where {$_.FullName.Split('\') -NotContains 'print'} | foreach {
# defining source path depending on whether a file or a folder is being piped
if ($_ -is [IO.DirectoryInfo]) {$source = [IO.DirectoryInfo]($_.FullName)}
if ($_ -is [IO.FileInfo])      {$source = [IO.DirectoryInfo]($_.DirectoryName)}
$source      | Write-Host -f Yellow
# defining destination path
[IO.DirectoryInfo]$destination = $newLocation + $source.toString().SubString($oldLocation.Length)
# making destination folder if it did not exist, and restore original folder attributes
if (-not ($destination|Test-Path)) {New-Item -path $destination -type directory -force | Out-Null
$destination.Attributes = $source.Attributes}
$destination | Write-Host -f DarkCyan
# moving contents to new location
$path = $source.toString()+'\*'
Move-Item -path $path -destination $destination -force # -verbose # -whatIf
''
}
# clean-up: remove empty folders that Move-Item might left behind in $oldLocation
Get-ChildItem $oldLocation -force -recurse -EA Silent|Where {$_.PSIsContainer -and @(Get-ChildItem -literal $_.FullName -force -recurse -EA Silent|Where {!$_.PSIsContainer}).Length -eq 0}|Remove-Item -force -recurse -EA Silent
User command (usercmd.ini)

Code: Select all

[em_test_moveProject_butPrint]
cmd=pwsh -c "%commander_path%\Plugins\PowerShell\moveProject_butPrint.ps1"
param=%P %T
User button

Code: Select all

TOTALCMD#BAR#DATA
em_test_moveProject_butPrint

WCMICONS.DLL
Move Project excluding Print(s)


-1
Prerequisites for 100% success
- a user must keep 'BRAND' root folder somewhere under the TotalCommander's active pane path, the closer to it the better.
- the TotalCommander's target pane path should somehow correspond to the desired destination.

Video illustration:
https://i.imgur.com/hVVW70d.mp4

This is how it works.
Last edited by beb on 2024-12-18, 07:26 UTC, edited 1 time in total.
#278521 User License
Total Commander [always the latest version, including betas] x86/x64 on Win10 x64/Android 10/15
pphktvmd
Junior Member
Junior Member
Posts: 2
Joined: 2024-12-13, 10:35 UTC

Re: Move the folder that does not contain inside a specific folder name

Post by *pphktvmd »

Ohhhhhh thank you very much for your help! It saved me hours of my life. The only thing left for me is to hunt down the folders that don't fit the above conditions. 😁 It actually worked and I was inspired to learn file management in powershell.
User avatar
beb
Power Member
Power Member
Posts: 579
Joined: 2009-09-20, 08:03 UTC
Location: Odesa, Ukraine

Re: Move the folder that does not contain inside a specific folder name

Post by *beb »

2pphktvmd
It's up to you to master any conditions to hunt down anything you want, using Where-Object as I did, or in any other way, for which PowerShell can be pretty flexible.

Get-ChildItem basics (see -include, -exclude, -filter, etc):
https://ss64.com/ps/get-childitem.html
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem

Where-Object basics:
https://ss64.com/ps/where-object.html
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/where-object

Code: Select all

get-something | where-object {
    $_.property1 -like "a*" -or
    $_.property2 -like "b*" -and
    $_.property1 -notlike "c*" -and
    $_.property2 -notlike "d*" -and
    $_.property4 -contents "e" -and
    $_.property5 -notcontents "f" -or
    $_.property8 -match ".*g.*" -and
    $_.property0 -notmatch ".*h.*"     
}
Glad it worked for you.
Cheers.
#278521 User License
Total Commander [always the latest version, including betas] x86/x64 on Win10 x64/Android 10/15
Post Reply