Move directory contents based off findstr - windows

Using windows 10 and I would like to recursively go through my movies folder and move any movies that have the genre Documentary written in it's associated nfo file. My directory structure is:
D:\Movie1
-Movie1.ext
-Movie.nfo
-Extrafanart\
D:\Movie2
-Movie2.ext
-Movie.nfo
-Extrafanart\
So, I want to search "movie.nfo" that will be located within each directory. If it has documentary genre, then I want to move that entire directory to a new location. The following I was able to get to work, but I'm only able to move the nfo file, not the directories' contents. I've been trying to work it out, but I can't figure it out:
for /F "tokens=*" %%I in ('findstr /i /s /m "<genre>Documentary</genre>" "D:\*.nfo"') do move "%%I" "E:\Documentaries\"
-EDIT-
So I have attempted to use powershell and I'm able to achieve the same thing, only moving the nfo, still can't move nfo's directory and contents:
get-childitem F:\Downloads\Movies\ -filter Movie.nfo -recurse | select-string -list -pattern "<genre>Documentary</genre>" | move -dest E:\Documentaries\

Here's my version of the solution:
# ECHO off
PUSHD %~dp0
CLS
CD Movies
FOR /D /r %%G IN ("*") DO (
findstr /C:"<genre>Documentary</genre>" "%%~G\*.nfo" >nul && (
ECHO "%%~G" is a Documentary!
MOVE "%%~G" C:\Documentaries
) || (
ECHO "%%~G" is NOT a Documentary!
)
)
CD ..
POPD
You may suppress the output of MOVE command as well like this:
MOVE "%%~G" C:\Documentaries >nul

Related

How do I drive through folders recursively in Windows Batch 'FOR /D /R' including root without '\.'?

Is there a way to recursively drive through folders in Windows Batch, and include the root folder you specify?
For example if I do:
FOR /D /R "C:\Users\Mark\Desktop" %%a in (*) do echo %%a
Results in:
C:\Users\Mark\Desktop\Folder1
C:\Users\Mark\Desktop\Folder2
C:\Users\Mark\Desktop\Folder2\SubFolder1
C:\Users\Mark\Desktop\Folder3
But no
C:\Users\Mark\Desktop
If I do:
FOR /D /R "C:\Users\Mark\Desktop" %%a in (.) do echo %%a
Results in:
C:\Users\Mark\Desktop\.
C:\Users\Mark\Desktop\Folder1\.
C:\Users\Mark\Desktop\Folder2\.
C:\Users\Mark\Desktop\Folder2\SubFolder1\.
C:\Users\Mark\Desktop\Folder3\.
Which kinda works, but I don't want the .\ in there.
Is there a way to get root folder and all subfolders to display like this:
C:\Users\Mark\Desktop
C:\Users\Mark\Desktop\Folder1
C:\Users\Mark\Desktop\Folder2
C:\Users\Mark\Desktop\Folder2\Subfolder1
C:\Users\Mark\Desktop\Folder3
I'm sure it's something simple but I haven't figured it out. Thanks.
try this one:
for /D /R "c:\users\jason\desktop" %%I in (.) do echo %%~fI >> out.txt

Windows Batch Script for moving files to different Folders based on File Name for Huge Data Volume

I have around 180K files which needs to be move to folders based on the file name.
Files are with different extensions. I need to take all file names which start with numbers and get the number untill the first '-' and make a folder. Move all the files with the number in the folder.
Need to exclude files which do not start with numbers.
Sample Data: File Names
123-ACBDHDJ.pdf
123-dhdjd.txt
5658-dgdjdk.txt
456477-gse.docx
For example; Based on the above data mentioned on Filenames Above, I want to do the following:
make folders 123, 5658 and 456477
Move the first two files in folder 123, 3rd file in folder 5658 and
last file in folder 456477.
Tried below script:
#echo off
setlocal enabledelayedexpansion
for %%A in (*.psd *.jpg *.html *.tif *.xls *.xlsx *.htm *.csv *.pdf *.docx *.TXT *.zip *.msg *.xlsb *.eml *.*) do (
echo file found %%A
for /f "delims=" %%B in ("%%A") do set fname=%%~nB
for /f "delims=" %%C in ("%%A") do set fextn=%%~xC
for /f "tokens=1* delims=-" %%D in ("!fname!") do set folname=%%D
echo folder name !folname!
if not exist "!folname!" (
echo Folder !folname! does not exist, creating
md "!folname!"
) else (
echo Folder !folname! exists
)
echo Moving file %%A to folder !folname!
move "%%A" "!folname!"
)
echo Finished
pause
Issues currently facing:
Folders created with alpha numeric characters as well, I wanted to
ignore those files and pick only the ones starting with numbers.
Script running too long, very slow performance . Data volume is
very high, 180K records.
Please help with a batch script for this or any faster way to do this as the data volume is very huge. Thanks in advance.
Let's consider why it takes long. You have 128k files, you run 4 loops, meaning the for loops themselfs process each file 5 times, that is 640 000 processes on its own, you then run echos for each, that is even more processes, then we you check if a folder exists and if not create it, the folder exists is another process.. I guess you are getting where I am going with this. You are effectively running over a million procces to complete this task.
Maybe we get rid of all the unwanted for loops, use * instead of naming each file, then get rid of delayed expansion as we can simply get away without having to set variables:
#echo off
for %%i in (*) do (
echo file found %%i
for /f "tokens=1* delims=-" %%a in ("%%i") do (
if "%%a-%%b"=="%%i" (
md %%a>nul
move "%%~fi" %%a
)
)
)
echo Finished
pause
As for the name and extension part, you never use them after setting, If you still want to somewhere use the name and extension of the files, then you just use them without having to set vars:
#echo off
for %%i in (*) do (
echo file found %%i
for /f "tokens=1* delims=-" %%a in ("%%i") do (
if "%%a-%%b"=="%%i" (
md %%a>nul
move "%%~fi" %%a
echo This is the file extension: %%~xi
echo This is the filename: %%~na
echo This is the filename, drive and path: %%~dpi
echo This is the filename with full path: %%~fi
)
)
)
echo Finished
pause
You are using a lot of unnecessary code, which makes your batch file too slow. I would suggest something like:
#echo off
for %%A IN (*.*) do (
if not "%%~fA" == "%~f0" (
echo File found: %%A
for /f "tokens=1* delims=-" %%B IN ("%%~nxA") do (
md %%B>nul
(move "%%~fA" "%%~dpA%%B")>nul
)
)
)
echo Finished
pause
exit /b %errorlevel%
It seems also that the other loops you are making are useless. You can directly use %%~nA, %%~xA, e.t.c. See output of for /? in cmd.
You may already have an answer with the .bat file scripts. Here is a way to do it in PowerShell. When the script is tested and will move the files correctly, remove the -WhatIf from the Move-Item cmdlet.
$sourcedir = './s'
$destdir = './d'
Get-ChildItem -File -Path "$sourcedir/*" |
ForEach-Object {
if ($_.Name -match '^(\d+)-.*') {
$ddir = Join-Path $destdir $Matches[1]
if (-not (Test-Path -Path $ddir)) { New-Item -Name $ddir -ItemType Directory }
Move-Item -Path $_.FullName -Destination $ddir -WhatIf
}
}
This can be run from a cmd shell by saving the script into a file (thefile.ps1) and using the following command or putting the command into a .bat file script.
powershell -NoLogo -NoProfile -File thefile.ps1
I would do it the following way -- see all the explanatory remarks (rem) in the code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=%~dp0." & rem /* (directory containing all the files; `%~dp0` points to the
rem parent directory of this batch script; to use the current
rem working directory, simply specify a single `.`) */
set "_MASK=?*-*.*" & rem /* (search pattern to find files, matching only files with at
rem least one hyphen in their names) */
set "_FILTER=^[0123456789][0123456789]*-" & rem /* (`findstr` filter expression;
rem this matches only files whose name begin with one or more
rem decimal digits followed by a hyphen) */
rem // Change to given root directory:
pushd "%_ROOT%" && (
rem // Loop through all matching files:
for /F "tokens=1* delims=-" %%E in ('
rem/ Return files and filter out those with non-numeric prefix: ^& ^
dir /B /A:-D "%_MASK%" ^| findstr /R /I /C:"%_FILTER%"
') do (
rem // Try to create target directory:
ECHO md "%%E" 2> nul
rem // Move file into target directory:
ECHO move /Y "%%E-%%F" "%%E\"
)
rem // Return from root directory:
popd
)
endlocal
exit /B
After having tested the script for correct output, remove both upper-case ECHO commands!

Moving specific extension up one directory level

My current folder structure goes as follows:
E:\Videos\Movies\Random Folder Name\Subs\Random File Name.srt
I would like to move my .srt files up one level so it reads:
E:\Videos\Movies\Random Folder Name\Random File Name.srt
I would prefer this to be a .bat file, but am willing to use PowerShell.
~EDIT~
I found something online that partially works and edited it to my needs:
#echo off
set thisdir=%cd%
for /f "delims=" %%A in ('dir /b /ad') do (
cd /d "%%~dpnA"
for /f "delims=" %%B in ('dir /b /ad') do (
echo Level 2 Directory: %%~dpnB
cd /d "%%~dpnB"
for /f "delims=" %%C in ('dir /b /ad') do (
echo Level 3 Directory: %%~dpnC
cd /d "%%~dpnC"
move *.srt ..\
cd..
rd "%%~dpnC"
)
)
)
This works, but only for the first folder, I can't seem to make Level 2 recursive as that is the level with random movie names. I tried replace for /f with for /r, but it was a no go.
Here's a one-liner:
forfiles /m *.srt /s /c "cmd /c move #file .."
Full code (you can run this from any drive now):
#echo off
cd /d E:\Videos\Movies\
for /r %%i in (*.srt) do move "%%~dpnxi" "%%~dpi.."
pause
This looks for all files with type .srt and moves them to the folder it was found in -1 directory (%%~dpi is the directory it was found in, adding .. to a path removes the last directory, so C:\Users\.. would put you at C:\).
PS: This time I have tested this, and it works.
Although the answers already given work, I still wanted to try and figure out how to perfect the code to my exact needs. Couldn't accomplish this with CMD, so I looked into powershell (which was easier for me to grasp for some reason) and coded this:
$sourcefolder = "F:\Videos\Movies\*\Subs\"
$files = Get-ChildItem -Recurse $sourcefolder | where {$_.PSIScontainer -eq $false}
foreach ($file in $files)
{
$destinationFolder = Split-Path -Parent $file.Directory.FullName
move-item $file.FullName $destinationFolder
}
It doesn't specify .srt files, but they are the only extension located in that folder. Thank you for the help guys!

Windows Batch folder exist and folder not exist

Have a need where we need to delete zip files that exist under a specific folder at 100 days old. All other zip files in the other folders, we can delete that are 30 days old. This would be easy if the files were a specific name, unfortunately we can only do this by folder name.
In the end result we will be using one of these techniques with FORFILES as we don't have to do a lot of logic programming in script.
Searched and did find how to do this and works OK, but the processing of the script is very slow.. Pretty much at this point, everything in the "NOT" somefolder condition is what takes quite a while to complete. Have done this with VBScript and PowerShell, but really want to get back to Batch Scripting for this.
BAT script to search directory for folders that match an input name
and as dbenham admits, again this is very slow. Also, did not like the fact that it does not show all folders in the "not" condition for the ones it does not find
He also states, that if you want to do extensive file/folder searching redirecting to a output file, maybe the best solution
This does work, but does not show the "not found" or the folders it would list..
dir /s /a-d c:\windows\*system32* >nul && (echo found it) || (echo not found)
This works to find all folders with system32 on a drive
dir /b /ad /s "c:\system32"
This works to look for folders that DO HAVE system32 within the results which are pretty quick too
FOR /f "tokens=*" %%G IN ('dir /b /ad /s c:\ ^| findstr /I /C:"system32"') DO echo %%G
We want to show all folders that DO NOT HAVE system32 within and in testing and redirecting to result.txt file, it created a 11.9MB file and will take quite a while to complete especially on a whole drive
FOR /f "tokens=*" %%G IN ('dir /b /ad /s c:\ ^| findstr /I /V /C:"system32"') DO echo %%G
How do I search for the directory of a file given its name using a batch script?
Not quite sure about this one
for /r c:\ %%F in (system32) if exist "%%F" echo %%~dpF
Playing around we get
For /F %%A IN('dir /s /a-d "c:\windows\*system32*") do && (echo found it) || (echo not found)
Are there any other ideas or Suggestions out there?
This will search in c:\files and below, and delete zip files by the following criteria:
In the folder called Special folder it will delete them if they are 100 days or older
otherwise it will delete them if they are 30 days or older.
Any zip file in the folders below the Special folder will be deleted at 30 days and older.
Test it before use.
#echo off
for /r "c:\files" %%a in (*.zip) do (
for %%b in ("%%~dpa\.") do (
if /i "%%~nxb"=="Special folder" (
forfiles /p "%%~dpa." /m "%%~nxa" /d -100 /c "cmd /c del #path"
) else (
forfiles /p "%%~dpa." /m "%%~nxa" /d -30 /c "cmd /c del #path"
)
)
)
pause

How to grab the names of all sub-folders in a batch script?

I just want to know how can I get all the names of the folders in a current directory. For example in my current directory I have three folders:
stackoverflow
reddit
codinghorror
Then when I execute my batch script all the three folders will print in the screen.
How can I achieve this?
Using batch files:
for /d %%d in (*.*) do echo %%d
If you want to test that on the command line, use only one % sign in both cases.
On Windows, you can use:
dir /ad /b
/ad will get you the directories only
/b will present it in 'bare' format
EDIT (reply to comment):
If you want to iterate over these directories and do something with them, use a for command:
for /F "delims=" %%a in ('dir /ad /b') do (
echo %%a
)
note the double % - this is for use in a batch, if you use for on the command line, use a single %.
added the resetting of default space delims in response to #Helen's comment
With PowerShell:
gci | ? { $_.PSIsContainer }
Old Answer:
With PowerShell:
gci | ? {$_.Length -eq $null } | % { $_.Name }
You can use the result as an array in a script, and then foreach trough it, or whatever you want to do...
For getting all the subfolders of a specific directory and display it in CMD :
#echo off
dir C:\input /s /b /o:n /a:d
Pause&Exit
For getting all the subfolders of a specific directory and save it in a text file :
dir C:\your_directory /s /b /o:n /a:d > output.txt

Resources