i have the following code in batch (cmd):
for /f "delims=" %%f in ('dir /b /s Example') do (
command
if %errorlevel%==1 (
command
SKIP
)
command
)
EDIT:
To make things more clear:
for /f... searches for a directory called 'Example' and loops to search for more directories than one.
the first command is a delete command, it deletes all files in the directory.
the command that happens when an error occurs, is a echo command which writes some info about the error to a text file.
now the hole skip thing; sometimes, the files can't be deleted because of access denied or this file is in use by.... Normally, what would happen if there weren't a skip thing, it would just stop the command and hang. So, what i want to do, is prevent this from happening. Alternatively, i want to use something like skip, so it can skip the file and continue anyways. So i think this command needs to be piped in the delete command.
I hope it's clear now.
Thanks in advance.
Like this?
for /f "delims=" %%f in ('dir /b /s Example') do (
command
if not errorlevel 1 (
command-for-success
) else (
command-for-error
)
)
Create the two command files and run delex.cmd. The files and directories that are not deleted will be logged to delex.txt. The ones that hang, will have a minimized cmd window open that gets killed after a delay by using ping (thanks to Doc Brown's suggestion).
delex2.cmd
----------
#echo off
del /q %1
if exist %1 echo %1 not deleted!>>delex.txt
exit
delex.cmd
---------
#echo off
if exist delex.txt del delex.txt
for /f "delims=" %%f in ('dir /s /b example') do start "delextaskkill" /min delex2.cmd "%%f"
ping 127.0.0.1 -n 3 -w 1000> nul
taskkill /fi "Windowtitle eq delextaskkill"> nul
Tested with:
\example
| file1
| file2
| file3
| file4
| file5
|
\---example
file1
file2
file3
file4
file5
When one uses del, and "access denied" or "this file is in use by..." occurs, %errorlevel% is 0, so testing %errolevel% is useless. Perhaps the following simple solution works in your case:
for /f "delims=" %%f in ('dir /b /s Example') do (
del %%f
if exist %%f (
echo "file not deleted"
) else (
echo "file deleted"
)
)
I believe that this is what you want
for /f "delims=" %%f in ('dir /b /s Example') do (
command
if not errorlevel 1 (
command
) else (
command
goto :eof
)
)
Perhaps this is more advanced than can be accomplished using just built-in cmd processing. Why not consider using the Windows Scripting Host (vbscript/jscript) or even PowerShell? Both will likely provide you the level of control you are requesting.
Try this batch file:
#echo off
REM For each directory named 'Example' ...
for /f "delims=" %%f in ('dir /b /s Example') do (
REM .. enter the directory and delete all the files found there.
pushd .
cd %%f
del /q *
for /f "delims=" %%z in ('dir /b') do (
REM Any files that still exist must have been inaccessable. Log an error.
echo Unable to delete file %%z > C:\logfile.txt
)
popd
)
Tested with the following directory structure:
folder\
|------Example\
| |-------file1 (write-protected)
| |-------file2
| |-------file3
|------deeper\
|-------Example\
|-------file4
|-------file5 (write-protected)
|-------file6
After running the batch file, only file1 and file5 were left. An "Access is denied" message was printed for each write-protected file encountered; if that gets annoying you re-direct the output of the batch file like script.bat > NUL to hide it.
So after all the existing answers didn't satisfy you and you absolutely need a skip within your batch file, i will make another try:
#echo off
setlocal
for /f "delims=" %%f in ('dir /b /s batch') do call :DoSomething %%f
goto end
:DoSomething
echo Here i am: %1
if %errorlevel%==1 goto :eof
echo No error occured
goto :eof
:end
endlocal
The trick is, that the for loop calls a sub function within the same file and gives the needed parameter to it. This new call runs in a new context and can only access the variables which are defined after the do call :DoSomething in the given order their.
So you have to access the variables here with %1, %2, etc. If you want to leave this context you have to make a goto :eof to jump to the end of the file (this marker is predefined in batch mode and should not occur within your file), what leaves the context and returns to the for loop.
After running through the whole loop we just jump to the :end marker, make a little clean up and are finished.
The following looks for the file extentions you want recursively under the "dirname" directory tree and executes commandstuff.bat against that file name:
for /r %i in (c:\dirname\*.ext) do
commandstuff "%i"
Commandstuff.bat looks like this:
#ECHO OFF del %1 IF (%ERRORLEVEL% ==
0) goto END
:ERROR Echo Error deleting %1
:END Echo end
This would run commandstuff.bat for you to delete the files you want. When there is an error it will simply echo the file details and continue processing the next file.
Related
Based on several articles on the internet I have written a batch script that:
scans defined location looking for .png files,
creates path to the new location for each file (..\first 4 characters of filename\first 9 characters of filename)
moves files to the new location
The script works fine, however I would like it to stop displaying errors and commands in command line window and display "PROCESSING..." instead? I have tried echo off, >nul and 2>nul with no success.
Here's the script:
#echo off
setlocal enabledelayedexpansion
cls
pushd E:\Archiwum\
for /f "tokens=*" %%1 in ('dir /a-d /b E:\Archiwum\*.png') do (
set filename=%%1&set dirname=!filename:~0,4!\!filename:~0,9!
if not exist E:\Archiwum\!dirname! (md E:\Archiwum\!dirname!)
move %%1 E:\Archiwum\!dirname!\
)
Here's a quick rewrite of your script
#Echo Off
If Exist "E:\Archiwum\*.png" (CD /D "E:\Archiwum") Else Exit /B
SetLocal EnableDelayedExpansion
ClS
For %%A In (*.png) Do (Echo Processing %%A
Set "filename=%%~nA"
Set "dirname=!filename:~,4!\!filename:~,9!"
If Not Exist "!dirname!\" MD "!dirname!"
If Exist "!dirname!\%%A" (Echo Name conflict %%A already exists.
) Else Move "%%A" "!dirname!" > Nul)
You need to be careful of spaces in your file names in order to prevent having directory names with trailing spaces as well as the other things I mentioned in my comments.
Thanks for your feedback. I made two modifications to your solution and now it works just fine.
#Echo Off
If Exist "C:\Archiwum\*.png" (CD /D "C:\Archiwum") Else Exit /B
SetLocal EnableDelayedExpansion
ClS
#Echo Processing...
#Echo Off
For %%A In (*.png) Do (
Set "filename=%%~nA"
Set "dirname=!filename:~,4!\!filename:~,9!"
If Not Exist "!dirname!\" MD "!dirname!"
If Exist "!dirname!\%%A" (Echo Name conflict %%A already exists.
) Else Move "%%A" "!dirname!" > Nul)
I added second #Echo Off - without it commands from for loop where still shown in command window.
I moved #Echo Processing as I wanted it to be shown only once with all of the operations done in the background.
Thank you a lot for your help.
the Batch File should scan a certain folder continuously for new csv files and whenever a new csv-file is placed in the folder, the csv-file should be renamed to a specific filename, because a firefox extension shall read that file.
I have already written a batch file for this but I think the solution is not perfect.
This is my attempt:
I start with the batch-file InitRun.bat:
#echo off
for /L %%i in (1,1,86400) do (
call FFRun1.bat
timeout /T 1
)
FFRun1.bat looks like this:
#echo off
FOR %%f in (*Data.csv) do (
echo %%f
set FILE=%%f
call :copy
)
goto end
:copy
copy /y %FILE% merged.csv
del %FILE%
call :RunFF
:RunFF
type merged.csv
pushd "C:\Program Files (x86)\Mozilla Firefox\"
start /wait firefox.exe
popd
:end
exit /b
If I place two or more csv-files at the same in the Folder, my solution can only process one csv and merged.csv only contains the last processed csv. In addition Firefox opens several windows, but also only works with the last csv which was copied to merged.csv.
Each new csv-File has the filename *Data.csv and should be renamed to merged.csv and for each new csv-file, firefox should start in a new tab and process the current merged.csv.
The csv-Files should not be renamed all at once, but one after another. Also Firefox should not start multiple windows/instances at a time.
I hope you can help me.
Regards,
Kepler
It should do what you indicate iterating over the directory in date order and converting the *data.csv into merge csv for later process (firefox changed with notepad for testing, adapt as neede). Also it will check if .csv files are in use, and wait for file to become available. If a file can not be processed (in use) no later file will be accesible until locked file become available (process files in generation order)
#echo off
setlocal enableextensions
set "folder=d:\temp"
set "files=*data.csv"
pushd "%folder%"
for /l %%a in (0 0 1) do (
if exist "%files%" (
echo files found
set "done="
for /f "tokens=*" %%d in ('dir /b /od "%files%"') do if not defined done (
call :replace "merged.csv" "%%d"
if not errorlevel 1 (
start "" /wait notepad "merged.csv"
) else (
set "done=1"
)
)
) else (
echo no files to process
)
timeout.exe /t 2 >nul
)
endlocal
exit /b
:replace target source
if exist "%~1" del /f /q "%~1" >nul 2>nul
if errorlevel 1 (
echo file "%~1" is in use
exit /b 1
)
ren "%~2" "%~1" >nul 2>nul
if errorlevel 1 (
echo file "%~2" is in use
exit /b 1
)
exit /b 0
I know this is dumb question but due to lack of my DOS knowledge i have facing trouble. I have a dir which have more than 98000 subdirs but many of them dont have any files i just want to list them with path
for now i am using this batch file
#echo off
for /d /r %1 %%A in (.) do (
dir /a /b "%%~fA" 2>nul | findstr "^" >nul || echo %%~fA
)
this is exactly does what i just want but the problem its not saving the list to a text file as lots of lots of dirs are empty cant copy from the cmd i tried with this code just modifying
#echo off
for /d /r %1 %%A in (.) do (
dir /a /b "%%~fA" 2>nul | findstr "^" >nul || echo %%~fA >epty.txt
)
but its just save one line not a list. what i want need just all list to be printed to a text file of this function.
Thanks again for your help
You could try redirecting the whole output from this script to a text file when you call it. E.g. if the first script you gave was saved to a file named script.cmd in your current working directory then you could call it from the command prompt using:
script.cmd > output.txt
for /F %%i in ('dir /b "C:\Program Files\Apache folder\*.*"') do (
echo Folder is NON empty
goto launch_app
)
How to check a folder is empty?
I tried above command, but it didn't work.
try this:
for /F %%i in ('dir /b /a "C:\Program Files\Apache folder\*"') do (
echo if you see this the folder is NOT empty
goto launch_app
)
File Not Found
#for /f "tokens=*" %%a in ('dir /b /a-d "C:\Progra~1\Apache"') do #...
The error that you see when you run this command, comes for the standard error output. But that is only a warning printed to your console. When this case happens, the body of the iteration won't be evaluated, and the algorithm based on this "for/dir" instruction, is in fact correct.
Now, if you want to get rid of this ugly error message, you need to add the following to your script, in order to redirect the standard error to null device:
2>NUL
so for instance, in a batch file, with the appropriate escape character:
#rem Print a list of file paths
#for /f "tokens=*" %%a in ('dir /b /a-d "%srcPath%" 2^>NUL') do #echo(%srcPath%\%%a
#echo off
cls
echo.
echo.
echo.
echo TEST FOR EMPTY DIRECTORY
echo was tested with "&" without a file
echo.
echo Can use Full or Subfolder path
echo (as below) of where test.bat
echo.
set p=Raw\
echo.
echo Just to show p is set
echo.
echo "p=%p%"
echo.
echo.
echo.
pause
for /F %%i in ('dir /b /a "%p%*"') do (
echo Folder %p% was NOT empty
goto :process
)
echo Folder %p% was empty
:process
echo "BLAH, BLAH, BLAH "
:end
pause
exit
rem Copy past in notepad to try. "Create and use or change the "raw" to your own fancy."
rem Hope this helps. Works great for me and I use it.
rem Have Fun.
rem Note use go to end next line after was empty. Worked great in w10. (this program hmm)
rem IF IT WORKS FOR YOU . GIVE A +. THX!
I wasn't satisfied with the given answers because I try to avoid for loops, goto and temp files whenever I can.
To check if the folder is empty:
dir /b /s /a "C:\Program Files\Apache folder\" | findstr .>nul || (
echo Folder is empty
)
To check if folder is not empty:
dir /b /s /a "C:\Program Files\Apache folder\" | findstr .>nul && (
echo Folder is NOT empty
)
dir C:\TEST\*.* /a/b/d/od>C:\TEMP\CHECKFOLDER
for /R C:\TEMP\ %%? in (CHECKFOLDER) do (
if "%%~z?"=="0" (
ECHO Folder is empty.
) ELSE (
ECHO Folder is NOT empty
)
)
I have a batch file that runs fine if I run it from the command prompt, but throws an error if it's called from Task Scheduler or run through Explorer. It appears that the syntax error occurs with the FOR logic.
#echo off
del mic_car*.txt
ftp -i -s:car_ftp_script.txt
pause
for /F %%I in ('dir /b/os mic_car*.txt') do (
echo %%I
pause
set tempfile=%%I
if exist %tempfile% (
del car_report.txt
ren %tempfile% car_report.txt
)
)
del mic_car*.txt
copy /y car_report.txt ..\car_report.txt
pause
If I run this from explorer or Task Scheduler, I see the files being transferred via FTP, followed by the syntax error. If I run it via command line, I see the echo of each file being processed and the largest file is copied to the higher level directory.
Your code cannot be working properly, even from the command line.
Your problem is your setting of tempfile and expansion of %tempfile% from within the same block of code. The value is expanded when the line is parsed, and all lines of the FOR statement are parsed in one pass. So your IF and REN statements are seeing the value that existed prior to entry of the loop.
Your code fails with a syntax error when tempfile is not defined. After expansion, the IF statement becomes invalid: if exist ( ..., hence the error.
The reason you think it works from the command line is because you probably ran the code once and it failed, but when finished, the tempfile variable is set, so the script will appear to run OK the next time you run it.
Normally I recommend the use of delayed expansion to enable setting and expanding a variable within a loop. But you don't have any reason to use tempfile at all - just use the FOR variable directly.
#echo off
del mic_car*.txt
ftp -i -s:car_ftp_script.txt
for /F %%I in ('dir /b/os mic_car*.txt') do (
echo %%I
if exist "%%I" (
del car_report.txt
ren "%%I" car_report.txt
)
)
del mic_car*.txt
copy /y car_report.txt ..\car_report.txt
pause
Actually, I don't understand why you need IF at all since your FOR loop only returns existing files. And all mic_car*.txt files will have been renamed car_report.txt (last one wins), so there should not be any need for your final DEL command.
You can combine the DEL and REN commands into one command by using MOVE
#echo off
del mic_car*.txt
ftp -i -s:car_ftp_script.txt
for /F %%I in ('dir /b/os mic_car*.txt') do (
echo %%I
move /y "%%I" car_report.txt >nul
)
copy /y car_report.txt ..\car_report.txt
pause
What version of Windows are you using?
I've changed the script to call a subroutine with the data extracted from your directory listing.
#echo off
del mic_car*.txt
ftp -i -s:car_ftp_script.txt
pause
for /F %%I in ('dir /b/os mic_car*.txt') do call :blue %%I
goto exit
:blue
echo -- processing %1 -------------
pause
set tempfile=%1
if exist %tempfile% (
del car_report.txt
ren %tempfile% car_report.txt
echo -- renamed %tempfile% to car_report.txt -------------
)
del mic_car*.txt
copy /y car_report.txt ..\car_report.txt
echo -- finished %1 -------------
pause
goto :eof
:exit
There is a difference in default directory between Windows Explorer and Scheduler, and for that reason, you should consider using explicit paths to the files and directories in which your object files are found. eg del c:\carfiles\mi_car*.txt, etc.
These lines are the cause of your error:
set tempfile=%%I
if exist %tempfile% (
%-Variables are expandet at parse time, i.e. when the command (in this case the for loop) is parsed by the interpreter. At this point, the loop variable doesn't have a value, so %tempfile% is empty, thus causing the error.
You need to enable delayed expansion and use !-variables inside the loop. These variables are expanded at runtime, when the loop variable contains actual values.
setlocal EnableDelayedExpansion
for /F %%I in ('dir /b/os mic_car*.txt') do (
echo %%I
pause
set tempfile=%%I
if exist !tempfile! (
del car_report.txt
ren !tempfile! car_report.txt
)
)