I have some folders like
Computer Idea
confidenze fatali
Casa Naturale sette
and files like
2021-09-01 computer idea.rar
into confidenze fatali.pdf
casa naturale sette 454.jpg
I try to move in this way
Computer Idea
|
|---> 2021-09-01 computer idea.rar
confidenze fatali
|
|---> into confidenze fatali.pdf
Casa Naturale sette
|
|---> casa naturale sette 454.jpg
For example, composed word computer idea
is found for both 2021-09-01 computer idea.rar
file and Computer Idea
folder (in this situation we have same 2 adjacent words).
Delimitator for composed word is simply an empty space.
I try to use this batch script but doesn't work, I ask also for a powershell solution so I add that tag in question.
@Echo off
Pushd %1
For /d %%A in (*) do For /f "delims=" %%B in (
'Dir /B "*%%~nxA*" 2^>Nul '
) do If "%%~nxA" NEQ "%%~nxB" Move "%%~fB" "%%~fA\" 2>&1>>Nul
Popd
CodePudding user response:
With PowerShell you do:
$rootFolder = 'D:\Test'
# get a list of folders inside the root folder
$subFolders = Get-ChildItem -Path $rootFolder -Directory
# next loop through the folders and find files that match their names
foreach ($folder in $subFolders) {
# use the foldername as filter, surrounded with wildcard characters (*)
Get-ChildItem -Path $rootFolder -Filter "*$($folder.Name)*" -File | Move-Item -Destination $folder.FullName -WhatIf
}
The -WhatIf
switch is a safety switch which will only show on screen what files would be moved without actually moving anything. If you find that info is correct, remove the -WhatIf
switch from the code and run again.
CodePudding user response:
I'm 99.9% sure there is a better way of doing this, but here's my take:
Get-ChildItem -Path "C:\Path" | Sort-Object -Property "Mode" |
ForEach-Object -Begin {
$files = @{}
} -Process {
if (-not $_.PSIsContainer) {
$files.Add($_.Name,$_.FullName) | Out-Null
}
else {
$folder = $_
$files.GetEnumerator() | ForEach-Object -Process {
if ($_.Key -match $folder.Name) {
Move-Item -Path $_.Value -Destination $folder.FullName -WhatIf
}
}
}
}
Since they are all located in the same directory, you can filter out which one is a file and which one is a folder by sending the files to a hashtable first; this is why we used Sort-Object
to organize by filetype listing files at the top. With the files being processed first in our if
statement, we know our else block (really not needed) will contain just folders. Finally, we can enumerate our hashtable in order to match file names to folder names. All that's left to do is move the files to their corresponding folder.
- Remove the
-WhatIf
common parameter when you've determined the results displayed are what you're after to perform the actual move.
CodePudding user response:
For /d %%A in (*) do Move "*%%A*" "%%A\" 2>&1>>Nul
Should work - Try it on a test directory first.
Given further information that some target directory names may be substrings of others...
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following setting for the source directory is a name
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
PUSHD "%sourcedir%"
:: remove variables starting #
FOR /F "delims==" %%b In ('set # 2^>Nul') DO SET "%%b="
FOR /f "tokens=1*delims=:" %%b IN ('dir /b /ad ^|findstr /n .') DO SET "#%%b=%%c"&SET /a count=%%b
:: find a directory that is not a substring of another & process it
:reselect
FOR /L %%b IN (1,1,%count%) DO IF DEFINED #%%b (
SET "targetstring=!#%%b!"
FOR /L %%c IN (%%b,1,%count%) DO IF %%b neq %%c IF DEFINED #%%c (FOR %%e IN ("!#%%b!") DO IF /i "!#%%c:%%~e=!" neq "!#%%c!" SET "targetstring=")
IF DEFINED targetstring (
SET "#%%b="
FOR /f "delims=" %%c IN ('dir /b /a-d "*!targetstring!*" 2^>nul') do Move "%%c" "!targetstring!\"
GOTO reselect
)
)
POPD
First, find the directorynames and store them in variable #1..#whatever
by submitting them to findstr /n
which prefixes each with serial:
Next, repeated scan the array of #n
variables, using targetstring
as a store of the string being examined. Compare it to each other string in the array and if it's a substring of another, clear targetstring
so if targetstring
survives, clear the #variable
that has this value, process the value and start over.
Repeat until all #variables have been processed - which means they are all deleted from the environment.