Can you recommend a way to list files on a WinXP disk that have a total file name (drive+folder+subfolder+filename+ext) greater than some value or MAX_PATH? Ideally this would be in batch or VB script. Thanks in advance.
#echo off
setlocal
if "%~1%~2"=="%~2%~1" (
echo Usage: drive maxlength
echo Example: %0 d: 200
goto :EOF
)
for /F %%A in ('dir /S/B/A:-D "%~d1\*" 2^>nul') do call :chkpath "%%~A" %2
goto :EOF
:chkpath
set #=%~1%
set len=0
:longer
if defined # (set "#=%#:~1%"&set /A len += 1&goto longer)
if %len% GTR %2 echo.%~1
goto :EOF
I would imagine that windows scripting host is faster...
Related
been trying to figure how to make the random string generation as a function, then call to function to return new random for each for loop.
but unable to make it work...
blank of idea, batch programming seems lot more complicated than web..
#echo off
GOTO :MAIN
:TestFunc
set orig=%1
set %~2=%random%
goto :eof
:MAIN
for %%a in (C:\folder\*.png) do (
set /a count+=1
set "fname=%%~a"
setlocal enabledelayedexpansion
set param_to_function=LetItBeA
call :TestFunc %param_to_function% return_value
set random=%return_value%
echo !random!
echo !fname!
ren "!fname!" img_%date:~10,4%-%date:~4,2%-%date:~7,2%_%HR%%time:~3,2%-!random!.png
endlocal
)
goto :eof
Original question answered (before edit). Explanation:
Use for /F against dir /b as unlike for /F, for starts parsing files immediately so it could get a renamed file again and again...
File renaming treated in a subroutine with test on file existence before ren.
Note endlocal&set "%1=%_RndAlphaNum%"&goto :eof tricky part how-to return a value to a variable (parameter) passed by reference.
ren command echoed merely for debugging purposes.
Resources (required reading):
An A-Z Index of the Windows CMD command line
Windows CMD Shell Command Line Syntax
The script:
#ECHO OFF
SETLOCAL enableextensions disabledelayedexpansion
Set /A "_RNDLength=6"
Set "_Alphanumeric=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
set "_folder=C:\folder"
for /F "delims=" %%a in ('dir /B "%_folder%\*.png"') do (
set /a count+=1
set "fname=%%~nxa"
call :renameFile
)
ENDLOCAL
goto :eof
:renameFile
call :getRandomString _RndANum
set "newFileName=img_%date:~10,4%-%date:~4,2%-%date:~7,2%_%HR%%time:~3,2%-%_RndANum%.png"
if exist "%_folder%\%newFileName%" goto :renameFile
echo ren "%_folder%\%fname%" "%newFileName%"
goto :eof
:getRandomString
rem usage
rem call :getRandomString varname
rem %1 = a variable name (pass by reference)
Setlocal EnableDelayedExpansion
Set "_Str=%_Alphanumeric%987654321"
:_LenLoop
IF NOT "%_Str:~18%"=="" (
SET _Str=%_Str:~9%
SET /A "_Len+=9"
GOTO :_LenLoop
)
SET _tmp=%_Str:~9,1%
SET /A _Len=_Len+_tmp
Set _count=0
SET _RndAlphaNum=
:_loop
Set /a _count+=1
SET _RND=%Random%
Set /A _RND=_RND%%%_Len%
SET _RndAlphaNum=!_RndAlphaNum!!_Alphanumeric:~%_RND%,1!
If !_count! lss %_RNDLength% goto _loop
rem do not split next line
endlocal&set "%1=%_RndAlphaNum%"&goto :eof
I have a folder with 46 different text files, from 001.txt to 046.txt and I need to add another file to, say, spot 30. Is there a ways to rename all the files from 030.txt until 046.txt up by one number, so there is an empty spot for the new 030.txt? (Operating on Windows 7)
You can use PowerShell, which is build-in in Windows 7:
46..30|Rename-Item -Path {'{0:000}.txt'-f$_} -NewName {'{0:000}.txt'-f($_+1)}
#ECHO Off
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
SET "insertat="
SET /p "insertat=Insert at which number ? "
IF NOT DEFINED insertat GOTO :EOF
SET /a insertat1=1%insertat%
SET /a howmany=1
SET /p "howmany=Insert How many ? [%howmany%]"
IF "%howmany%"=="0" GOTO :EOF
FOR /f "delims=" %%a IN (
'dir /b /o-n /a-d "%sourcedir%\*.txt" '
) DO (
CALL :isnum %%~na
IF NOT DEFINED notnumber SET /a maxnum=1%%~na&GOTO insert
)
ECHO maxnum NOT found
GOTO :eof
:insert
SET /a newnum=maxnum + howmany
IF EXIST "%sourcedir%\%maxnum:~1%.txt" ECHO(REN "%sourcedir%\%maxnum:~1%.txt" %newnum:~1%.txt
SET /a maxnum -=1
IF %maxnum% GEQ 1%insertat% GOTO insert
GOTO :EOF
:: Determine whether %* is purely numeric
:isnum
SET "notnumber=%~2"
IF DEFINED notnumber GOTO :EOF
SET "notnumber=9%~1"
FOR /l %%z IN (0,1,9) DO CALL SET "notnumber=%%notnumber:%%z=%%"
GOTO :eof
I may as well post this regardless.
It automatically locates the highest filenumber and allows any number of slots to be inserted (default of 1 for Enter)
You would need to change the setting of sourcedir to suit your circumstances.
The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(REN to REN to actually rename the files.
Here is a simple pure batch solution
#echo off
setlocal enableDelayedExpansion
set increment=1
set "start=030"
for /f %%F in (
'dir /b /a-d /o-n ???.txt^|findstr /rx "[0-9][0-9][0-9]\.txt"'
) do if "%%~nF" geq "%start%" (
set /a new=1%%~nF+increment
ren %%F !new:~1!%%~xF
)
I have a batch file that will display all files in a folder and allow the user to select a file by number and pass it to an executable. Everything works, however, I am trying to make this a click-and-forget type of batch file. In other words, I would also like the user to be able to select a number that would pass all files, one at a time, to said executable. My current code is as follows:
#ECHO OFF
SET index=1
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%f IN (*.txt) DO (
SET file!index!=%%f
ECHO !index! - %%f
SET /A index=!index!+1
)
SETLOCAL DISABLEDELAYEDEXPANSION
SET /P selection="select file by number:"
SET file%selection% >nul 2>&1
IF ERRORLEVEL 1 (
ECHO invalid number selected
EXIT /B 1
)
CALL :RESOLVE %%file%selection%%%
CSCRIPT //NoLogo //B C:\FCLoader\sendkeys.vbs
Z:\executable.exe %file_name%
GOTO :EOF
:RESOLVE
SET file_name=%1
GOTO :EOF
The CSCRIPT line is there to pass keystrokes from a vbs file to enter username, password, and a database name to the executable. This works fine. The executable works fine too if I just want to run it once against one file. Below is an example of what the batch looks like after running:
1 - file.txt
2 - file2.txt
3 - file3.txt
select file by number:
What I would like is for it to look like this:
1 - file.txt
2 - file2.txt
3 - file3.txt
4 - All
select file by number:
I would like for the user to be able to select 4 - All, and have it run the executable for every file, one at a time. When the first run through completes, it will call the executable again and so on...It will also need to run the vbs script before the executable is run in order for the credentials to be passed as stated above.
I have used the extent of my knowledge in Batch Files and now need help.
Try this code:
#ECHO OFF
SET index=1
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%f IN (*.*) DO (
SET file!index!=%%f
ECHO !index! - %%f
SET /A index=!index!+1
)
echo/!Index! - All
SETLOCAL DISABLEDELAYEDEXPANSION
SET /P selection="select file by number: "
if "%selection%" equ "%index%" goto allFiles
SET file%selection% >nul 2>&1
IF ERRORLEVEL 1 (
ECHO invalid number selected
EXIT /B 1
)
CALL :RESOLVE %%file%selection%%%
CSCRIPT //NoLogo //B C:\FCLoader\sendkeys.vbs
Z:\executable.exe "%file_name%"
GOTO :EOF
:RESOLVE
SET file_name=%1
GOTO :EOF
:allFiles
FOR %%f IN (*.txt) DO (
CSCRIPT //NoLogo //B C:\FCLoader\sendkeys.vbs
Z:\executable.exe "%%f"
)
goto :EOF
Pick a file from a numbered list 1 to [a lot]!
This uses the choice command if less than 10 files (max files > 9999?? untested)
Files are numbered starting at 1 (not 0) - so 1-9.
Choice has timeout and default - but if more than 9 files no timeout
If more than 9 files and user presses ENTER key it uses the default value
Files are listed in date/time order - most recent first
A path and wildcard filter (* or ?) can be set for the dir command.
It could be adapted to run ALL as requested?
#echo off
SETLOCAL ENABLEEXTENSIONS
SETLOCAL ENABLEDELAYEDEXPANSION
mode con: cols=185 lines=90
COLOR 1F
set MYPATH="G:\Downloads\*.iso"
set DEFAULT=1
set TIMEOUT=3
:GETISO
echo.
echo ISO FILES IN %MYPATH%
echo.
set count=1
set choose=
for /f "tokens=*" %%i in ('dir %MYPATH% /b/a-d/od/t:c') do (echo !count! %%i & set choose=!choose!!count!& set /A count=!count!+1)
echo.
set /a count=%count%-1
if %count%==0 echo NO FILES FOUND! & goto :EOF
if %count% LSS 10 CHOICE /C "%choose%" /N /M "SELECT DESIRED ISO (1-%count%) : " /T %TIMEOUT% /D %DEFAULT%
if %count% LSS 10 set /A ask=%errorlevel%+0
if %count% GEQ 10 (
set ask=%DEFAULT%
set /P ask="SELECT DESIRED ISO (1-%count%) : "
set /A ask=%ask+0
)
if "%ask%"=="" echo INPUT ERROR! & goto :GETISO
if "%ask%"=="0" echo INPUT ERROR! & goto :GETISO
if %ask% GTR %count% echo ERROR - NUMBER TO BIG! & goto :GETISO
set count=1
for /f "tokens=*" %%i in ('dir %MYPATH% /b/a-d/od/t:c') do (
if !count!==%ask% set FILE=%%i
set /A count=!count!+1
)
echo.
echo FILE=%ask% %FILE%
Must work on XP/Vista/7. Can use batch, VBS, or whatever else anyone with the mentioned O/Ses can run (except PE).
Need to choose 15 random files, and also similarly named folders (which are in a different location), and copy them to their own folder at the same time.
I've scoured google and websites like robvanderwoude.com, and found a few close examples, but I'm too inexperienced to adapt the examples to what I need without going cross-eyed. I'd appreciate it if anyone could point me in the right direction (most efficient/easiest method to use), or some example possibly with a brief explanation I can also learn from.
Layout description:
30 files:
%~dp0\mod\store\XMLs -> %~dp0\mod\0.1.2\map\data
map01_aaa.xml
map02_bbb.xml
map03_ccc.xml
...
map60_zzz.xml
30 folders:
%~dp0\mod\store\models -> %~dp0\mod\0.1.2\sky\stuff
01_aaa_map
02_bbb_map
03_ccc_map
...
60_zzz_map
The code below is what I'm trying to adopt this to, but it only chooses 15 files/folders in order. Tried using the %random% environment var in an equation for SrcMax, but that just chooses a random amount of files and always starts with the first file.
(old code)
rem #ECHO OFF
setlocal ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS
SET SrcCount=0
SET SrcMax=15
FOR %%F IN (%~dp0\mod\store\XMLs\*.*) DO IF !SrcCount! LSS %SrcMax% (
SET /A SrcCount += 1
ECHO !SrcCount! COPY %%F %~dp0\mod\0.1.2\map\data\
COPY %%F %~dp0\mod\0.1.2\map\data\
SET FNAME=%%~nF
ECHO XCOPY /s "%~dp0\mod\store\Models\!FNAME:~3!_map" "%~dp0\mod\0.1.2\sky\stuff\!FNAME:~3!_map\"
XCOPY /s "%~dp0\mod\store\Models\!FNAME:~3!_map" "%~dp0\mod\0.1.2\sky\stuff\!FNAME:~3!_map\"
)
I believe this should work.
#echo off
setlocal enabledelayedexpansion
set XMLs_src=.\mod\store\XMLs
set XMLs_dest=.\mod\0.1.2\map\data
set maps_src=.\mod\store\models
set maps_dest=.\mod\0.1.2\sky\stuff
rmdir /q /s "%XMLs_dest%" 2>NUL
rmdir /q /s "%maps_dest%" 2>NUL
mkdir "%XMLs_dest%"
mkdir "%maps_dest%"
for /L %%X in (1,1,15) do (
call :rnd rn
call :xml !rn!
call :map !rn!
)
copy "%XMLs_dest%\*.*" "%XMLs_src%" >NUL
echo d | xcopy /q /f /e /y "%maps_dest%\*" "%maps_src%" >NUL
echo Done.
goto :EOF
:rnd
set c=0
for /d %%I in (%maps_src%\*) do set /a c+=1 >NUL
set /a %1=%RANDOM% * %c% / 32768 + 1 >NUL
goto :EOF
:xml
set c=0
for /f %%I in ('dir /b /o:n "%XMLs_src%"') do (
set /a c+=1 >NUL
if !c!==%1 (
echo %XMLs_src%\%%I -^> %XMLs_dest%\%%I
move "%XMLs_src%\%%I" "%XMLs_dest%" >NUL
goto :EOF
)
)
goto :EOF
:map
set c=0
for /f %%I in ('dir /b /o:n "%maps_src%"') do (
set /a c+=1 >NUL
if !c!==%1 (
echo %maps_src%\%%I -^> %maps_dest%\%%I
echo d | xcopy /q /f /e /y "%maps_src%\%%I" "%maps_dest%\%%I" >NUL
rmdir /q /s "%maps_src%\%%I"
goto :EOF
)
)
goto :EOF
It basically moves to prevent duplication, then copies from destination back to source to restore what was moved away.
I would like to call for help on my attempt to create a script which will automatically check last modified file and transfer it to destination.
What I have is this:
#Echo Off
Set _Delay=1
for /f "tokens=1,2,3 delims==" %%a in (config.ini) do (
if %%a==source set _Monitor=%%b
if %%a==destination set _Dest=%%b
if %%a==timer set _Timer=%%b
)
Set _Base=%temp%\BaselineState.dir
Set _Chck=%temp%\ChkState.dir
Set _OS=6
Ver|Findstr /I /C:"Version 5">Nul
If %Errorlevel%==0 Set _OS=5 & Set /A _Delay=_Delay*1000
Goto :_Xfer
:_StartMon
#echo off
SET R1=Start /w Sync1.vbs
Call :_SetBaseline "%_Base%" "%_Monitor%"
:_MonLoop
If %_OS%==5 (Ping 1.0.0.0 -n 1 -w %_Delay%>Nul) Else Timeout %_Delay%>Nul
Call :_SetBaseline "%_Chck%" "%_Monitor%"
FC /A /L "%_Base%" "%_Chck%">Nul
If %ErrorLevel%==0 Goto _MonLoop
::
for /l %%a in (%_Timer%,-1,0) do (
#Echo::::::::::::::::::::::::::::::::::::::::::::::
#Echo:: SEC Auto Transfer ::
#Echo:: Aizal 16 June 2012 ::
#Echo::::::::::::::::::::::::::::::::::::::::::::::
#Echo This script will scan SEC Data Folder for
#Echo new files every 30 minutes and will copy
#Echo it to the Server. Make sure you set correct
#Echo folder before using this script.
ECHO.
ECHO Currently recording:
FOR /F %%a in ('xcopy "%_Monitor%\*.SEC" "%_Dest%" /L /Y') DO (
IF NOT EXIST "%_Dest%.\%%~nxa" ECHO %%~nxa
)
ECHO Refreshing...
ECHO Please wait %%a seconds...
%R1%
cls
)
::
:_Xfer
FOR /F %%a in ('xcopy "%_Monitor%\*.SEC" "%_Dest%" /L /Y') DO (
IF NOT EXIST "%_Dest%.\%%~nxa" xcopy "%%a" "%_Dest%" /Y
)
::
Echo.Change Detected
ECHO.
Goto :_StartMon
:::::::::::::::::::::::::::::::::::::::::::::::::::
:: Subroutine
:::::::::::::::::::::::::::::::::::::::::::::::::::
:_SetBaseline
If Exist "%temp%\tempfmstate.dir" Del "%temp%\tempfmstate.dir"
For /F "Tokens=* Delims=" %%I In ('Dir /S "%~2"') Do (
Set _Last=%%I
>>"%temp%\tempfmstate.dir" Echo.%%I
)
>"%~1" Findstr /V /C:"%_Last%" "%temp%\tempfmstate.dir"
Goto :EOF
Now, if you noticed the script will compare the content of source folder with the content of the destination folder and will copy the files from source if there is not already file in destination. I would like to know if someone can help me figuring out how to make the script to check the last modified file in source folder and ONLY copy it to the destination AND if the said file is currently in use/being write to then script will wait until it finished before trying to copy it again.
Also, right now I have to edit source.ini file to specify which folder I want to monitor and each time I have to change the subfolder path to watch for changes, is there a way to watch parent folder for any new files and take that file to the destination?
I found this script on the net but hoping to check the file not based on day but instead of time.
::Copy Files Made Or Modified Today
#echo off
setlocal
set source= <source directory>
set dest= <destination directory>
pushd "%source%"
set t=%date:~4%
::for /f %%a in ('dir /b /a-d /o-d') do call :PROCESS "%%a"
goto :eof
popd
:PROCESS
for /f %%j in ('echo %~t1') do set d=%%j
if "%d%"=="%t%" copy %1 "%dest%"
goto :eof
Hope to find the solution from here.
Many thanks
With this you'll get the last modified file:
for /f %%A in ('dir /b /tw /o-d not-mandatory-file-mask') do (
set last_file=%%A
goto :endloop
)
:endloop
With this you'll copy the file if it is possible. If not it will try again and again:
:tryagain
set /a errorlevel=0
copy some_dir\%last_file% %destination%
if %errorlevel% NEQ 0 (
sleep 10
goto :tryagain
) else (
goto :end
)
:end