I'm in need of a batch command that will look into a directory's sub folders and find a partial file name. If that file exists, then move that directory otherwise leave it alone.
I have a folder full of movies:
D:\Movies\movie1\
\movie2\
\movie3\
Within each movie folder I would like to know if it has a trailer downloaded into the folder, if so then move that directory to x:\movies. I say partial file name as every trailer file will include the title of the movie with "-trailer" added to the end (f.e. The Interview (2014)-trailer).
Let's look for a solution from Windows CLI (Command Line Interpreter) with -> prompt using An A-Z Index of the Windows CMD command line and with next scenario:
->tree d:\test\movies
D:\TEST\MOVIES
├───movie1
├───movie2
├───movie3
└───movie4
->tree d:\test\xmovies
D:\TEST\XMOVIES
No subfolders exist
->dir /B /S /A-D "d:\test\movies"
d:\test\movies\movie1\The View (2014)-trailer missing.rtf
d:\test\movies\movie2\The Interview (2014)-trailer.bat
d:\test\movies\movie2\The Interview (2014)-trailer.bmp
d:\test\movies\movie2\The Interview (2014)-trailer.txt
d:\test\movies\movie3\An Interview (2014)-trailer.bmp
To find all those files under MOVIES subfolder with -trailer added to the filename end preceding . of file extension:
->dir /B /S /A-D "d:\test\movies\*-trailer.*"
d:\test\movies\movie2\The Interview (2014)-trailer.bat
d:\test\movies\movie2\The Interview (2014)-trailer.bmp
d:\test\movies\movie2\The Interview (2014)-trailer.txt
d:\test\movies\movie3\An Interview (2014)-trailer.bmp
To get folder names only:
->for /F "tokens=*" %G in ('dir /B /S /A-D "d:\test\movies\*-trailer.*"') do #echo %~dpG
d:\test\Movies\movie2\
d:\test\Movies\movie2\
d:\test\Movies\movie2\
d:\test\Movies\movie3\
But here the movie2 appears more than once! And, moreover, the move command does not allow source directory with trailing backslash:
->move "D:\test\Movies\movie4\" "D:\test\xMovies\"
The system cannot find the file specified.
->move "D:\test\Movies\movie4" "D:\test\xMovies\"
1 dir(s) moved.
Therefore we need switch from Windows shell (CLI) to batch scripting. Create file 28167824.bat (e.g with notepad and save it to D:\bat\StackOverflow folder):
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
for /F "tokens=*" %%G in (
'dir /B /S /A-D "d:\test\movies\*-trailer.*"'
) do (
set "rawfolder=%%~dpG"
if exist "%%~dpG" call :moveDir
)
:endlocal
#ENDLOCAL
goto :eof
:moveDir
set "srcfolder=%rawfolder:~0,-1%"
`enter code here`echo move "%srcfolder%" "d:\test\xMovies\"
rem move "%srcfolder%" "d:\test\xMovies\"
goto :eof
Run this batch script, the template of next move commands is the same as in that successful move command mentioned above:
->D:\bat\StackOverflow\28167824
move "d:\test\Movies\movie2" "d:\test\xMovies\"
move "d:\test\Movies\movie2" "d:\test\xMovies\"
move "d:\test\Movies\movie2" "d:\test\xMovies\"
move "d:\test\Movies\movie3" "d:\test\xMovies\"
Bingo! Now we could remove rem before move "%srcfolder%" "d:\test\xMovies\", save the script and run it:
->D:\bat\StackOverflow\28167824
move "d:\test\Movies\movie2" "d:\test\xMovies\"
1 dir(s) moved.
move "d:\test\Movies\movie3" "d:\test\xMovies\"
1 dir(s) moved.
And here is final configuration, cf. starting scenario:
->tree d:\test\movies
D:\TEST\MOVIES
└───movie1
->tree d:\test\xmovies
D:\TEST\XMOVIES
├───movie2
├───movie3
└───movie4
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
For example
consider:
H:\reports\test\12345\dailynews.pdf
I want to send this PDF through mail by using MSSQL job (sql server 2008 R2).
But every time when another job creates the pdf file the location changes.
like
H:\reports\test\48596\dailynews.pdf
I need a batch program to find the folder name which is present after the test folder.
A recursive check may report same named files existing elsewhere in the tree and may take longer. My suggestion is to use this instead:
#Echo Off
Set "MyFile="
For /D %%A In ("H:\reports\test\*"
) Do If Exist "%%A\dailynews.pdf" Set "MyFile=%%~fA\dailynews.pdf"
If Not Defined MyFile Exit/B
Echo %%MyFile%% = %MyFile%
Regarding the given info, I would suggest to
split the string at the backslashes and extract the 4th element like this:
set p=H:\reports\test\12345\dailynews.pdf
for /F "delims=\ tokens=4" %%a in ("%p%") do echo %%a
Note the double quotes ("%p%"), so it gets interpreted as string (and not as a filename or command).
If you want to make sure, that the 3rd element is the test folder, then I would suggest:
set p=H:\reports\test\12345\dailynews.pdf
set o=H:\reports\live\55555\dailynews.pdf
for /F "delims=\ tokens=3,4" %%a in ("%p%") do if "%%a"=="test" echo %%b
for /F "delims=\ tokens=3,4" %%a in ("%o%") do if "%%a"=="test" echo %%b
Outputs 12345 but not 55555, which is in the live folder.
Edit:
I realized that my answer left out completely, how one can detect the newest dailynews.pdf, which is what the OP probably looking for.
Like the dailynews routine runs at 21.00, and you want to mail that report at 22.00. (Again, yet another assumption.)
IMO, the tricky part is to parse and compare the date/time info of the files.
A simple dir dailynews.txt /S /O:-D does not work with subdirs.
So...
#echo off
cls
set base=H:\reports\test
set filename=dailynews.pdf
set current_date=19000101
set current_time=0000
set current_file=
::debug output
dir "%filename%" /S /O:-D
:: inspect each entry
for /F "usebackq" %%a in (`dir "%filename%" /S /B /O:-D`) do call :inspect "%%a"
:: all done, quit
goto :quit
:: subroutine for comparing current with actual newest entry
:inspect
echo %1
set _date=
set _time=
:: get comparable date time info
:: change to your regional date/time settings/locale! (german here)
:: maybe check SO for other locales
for /F "usebackq tokens=1,2,3,4,5 delims=.: " %%a in (`dir %1^|findstr "%filename%"`) do echo %%a %%b %%c %%d %%e&set _date=%%c%%b%%a&set _time=%%d%%e
:: we have to split in two components, otherwise it seems too big for comparing
if /I %_date% LSS %current_date% goto :eof
if /I %_time% LSS %current_time% goto :eof
:: this one is newer! set new values
set current_date=%_date%
set current_time=%_time%
set current_file=%1
goto :eof
:quit
set current_
Performance may get worse if you dont clean up the basedir at some time.
I have this really nice line in my batch file that tells me how many lines are in a file:
find /v /c "" C:\Users\c1921\mypath\myfolder\!$Unit!.txt
This is nice and gives me 31 for the particular file I'm working with. My problem is the file looks something like this:
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
my_handled
219278
check
219276
control
219274
I want to be able to skip the first three lines entirely and then save the first value and then use the second value in my next command etc.
How do I save the number (e.g. 31) into a variable in my batch file?
On a hunch I tried setting a variable like so but it wasn't effective:
set "$testVar="""
echo !$testVar!
This command allows you to "save the number (e.g. 31) into a variable in my batch file":
for /F %%a in ('find /v /c "" ^< C:\Users\c1921\mypath\myfolder\!$Unit!.txt') do set numLines=%%a
This command allows you "to skip the first three lines entirely" and process the rest:
for /F "skip=3 delims=" %%a in (C:\Users\c1921\mypath\myfolder\!$Unit!.txt) do echo Processing: "%%a"
However, in my opinion this problem could be entirely avoided if the three first lines in the text file are supressed from the very beginning. I think this file is generated via a VBScript of JScript program that is executed this way:
cscript progname.vbs > C:\Users\c1921\mypath\myfolder\!$Unit!.txt
The first three lines in the text file may be avoided adding //nologo switch this way:
cscript //nologo progname.vbs > C:\Users\c1921\mypath\myfolder\!$Unit!.txt
#ECHO OFF
SETLOCAL
SET /a count=3
SET "first="
FOR /f "skip=3delims=" %%a IN (q25089468.txt) DO (
IF DEFINED first (CALL :show %%a) ELSE (SET "first=%%a")
)
ECHO count=%count%
GOTO :EOF
:show
ECHO first=%first% second=%1
SET /a count+=2
SET "first="
GOTO :eof
I used a file named q25089468.txt containing your data for my testing.
You appear to be asking two entirely different things - how to count the lines and how to skip the first 3, then deliver each succeeding pair to another process.
I need a robocopy script that can run to replicate data from a source to a destination. the problem I have is I need to replicate certain folders from the source from different drives over to a destination server which will need to go to different drives also.
I'm using this script to copy a single folder over to the destination server (which this is running on)
#echo off
SET Day=%date:~6,4%.%date:~3,2%.%date:~0,2%
SET _source=\\10.10.10.18\R$\User\customer1
SET _target=E:\customer1
SET _log=E:\test_%Day%_Replication_Log.txt
SET _what=/MIR /COPYALL /B
SET _options=/NS /NC /NFL /NDL /R:0 /W:0 /RH:0615-1730 /MON:900 /MOT:30 /LOG+:"%_log%"
robocopy %_source% %_target% %_what% %_options%
I have a number of folders on the R drive as well as other drives that I wish to copy like this but I ideally dont want separate jobs for each and would like to run it under one batch file if possible.
Is there a way of having the source location specified in a text document and having the script read this and pass it to the command same would I also be able to specify the destination for this data i.e.:
customer1 - e drive
customer2 - f drive
etc
I would like this as easy as possible so that folders can be added / removed from the text file so the commands don't need to be altered.
Is this possible?
I think you are going to need to do something like the following..
SET _source=\\10.10.10.18\R$\User\customer1
rem SET _source=C:\windows
SET _target=E:\customer1
SET _log=E:\test_%Day%_Replication_Log.txt
SET _what=/MIR /COPYALL /B
SET _options=/NS /NC /NFL /NDL /R:0 /W:0 /RH:0615-1730 /MON:900 /MOT:30 /LOG+:"%_log%"
for /f "tokens=1*delims=-" %%a in ('dir /B/ad/s %_source%\drive*') do (
robocopy %%a %_target% %_what% %_options%
)
pause
Now, what I suspect you are going to need to do is something like the following..
Notice the oddball: "%~p0" - if you go to CMD (command line) and type in FOR /? - it will explain what these mean.. It like two or three screens in on the help..
SET _source=\\10.10.10.18\R$\User\customer1
rem SET _source=C:\windows
SET _target=E:\customer1
SET _log=E:\test_%Day%_Replication_Log.txt
SET _what=/MIR /COPYALL /B
SET _options=/NS /NC /NFL /NDL /R:0 /W:0 /RH:0615-1730 /MON:900 /MOT:30 /LOG+:"%_log%"
for /f "tokens=1*delims=-" %%a in ('dir /B/ad/s %_source%\drive*') do (
cd "%~p0%_source%\drive"
copy *.txt "%~p0 %_source%\drive"
FOR /F "delims=" %%A IN ('type %~p0ALIST.txt') do (
rem cd "%~p0%%A\%_target%"
rem copy *.txt "%~p0%%A\%_target%"
robocopy %%a %_target% %_what% %_options%
rem cd "%~p0%%A\drive"
)
pause
I'm in the middle of writing a batch script that will copy a bunch of tiny files from one location to another, verify that the file exists in the new directory, delete the original, and move on. I've implemented a FOR loop to do this, but I can't seem to get it working. Any ideas?
::Copying files-
::For loop copies file, verifies file was copied,
::and removes file from source.
for %%f in (Q:%source%\*) do (
:recopy
copy %%f %dest%\%%f
if not exist %dest%\%%f goto recopy
set /a count+=1
del %source%\%%f
echo copied !count! of %total%
ping -n 1 -w 500 1.1.1.1 >nul
)
The inputs for the variables are as follows:
set /P source=Enter path to files on P:(Temp) drive (EX: jdoe\copy)
set dest=D:Temp\Copy
Scripted adding if network share is as follows:
net use Q: \\SERVER\Temp
The error given is:
The system cannot find the file specified
and the error is repeated until the screen fills.
Full pastebin at http://pastebin.com/yjXP7H6U
You can't have a label within a for loop or if statement if memory serves. You should move :recopy outside the loop. Something like this:
::Copying files-
::For loop copies file, verifies file was copied,
::and removes file from source.
for %%I in (Q:\%source%\*) do (
call :recopy "%%~fI" "%dest%\%%~nxI"
set /a count+=1
del "%%~fI"
echo copied !count! of %total%
ping -n 1 -w 500 1.1.1.1 >nul
)
goto :EOF
:recopy source dest
copy "%~1" "%~2"
if not exist "%~2" call :recopy "%~1" "%~2"
goto :EOF
I'm stuck on a dead end with this logparser dilemma. so there's no where else to go but here.
Batch file (disktrend.bat)
#echo off
pushd "Program Files (x86)\Log Parser 2.2\"
for /f "tokens=1,2 delims=," %%A in (d:logs\serverdrives.txt) do #logparser -i:tsv file:D:\logs\disktrend.sql?sd=%%A -o:chart -charttype:line > D:\logs\%%B.gif
SQL file (disktrend.sql)
SELECT date,pfree using to_int(sub(to_real(100),to_real(replace_chr(free,'%','')))) as pfree,replace_chr(strcat(server,drive),':','') AS serverdrive from d:\logs\compiled\*.log where serverdrive =%sd%
List file (serverdrives.txt)
'SERV06F',SERV06F
'SERV00F',SERV00F
Log file sample content (*.log)
Date Server Drive Free Free Space Total
20120914 SERV06 F: 79.55% 27619.02MB 34719.82MB
20120914 SERV00 F: 99.73% 34630.37MB 34723.81MB
When I run the batch script, I get below error:
Error
Invalid output filename ""
Invalid output filename ""
Does anyone know how to solve this?
while eating dinner an answer suddenly popped on me.
I edited the Batch and SQL files.
See below.
Batch file (disktrend.bat)
#echo off
pushd "Program Files (x86)\Log Parser 2.2\"
for /f "tokens=1,2 delims=," %%A in (d:logs\serverdrives.txt) do #logparser -i:tsv file:D:\logs\disktrend.sql?sd=%%A+filen=%%B -o:chart -charttype:smoothline -q:off -stats:off
SQL file (disktrend.sql)
SELECT to_string(date),pfree using to_int(sub(to_real(100),to_real(replace_chr(free,'%','')))) as pfree,replace_chr(strcat(server,drive),':','') AS serverdrive into d:\logs\%filen%.gif from d:\logs\compiled\*.log where serverdrive =%sd%