Batch forfiles error path not found - batch-file

I'm a bit of a newbie with batch files, but am looking for a script to delete .txt log files that are older than 30 days... (FWIW, I am on XP SP3...)
I tried to follow the example found here, (including downloading the forfiles.exe from here) and ended up with this:
forfiles -p"D:\SQL Database Back Ups\Update_FmlaManagement_Log" -s -m *.txt -d-30 -c "cmd /c del #FILE"
But I get this error:
Error path not found (3rd argument) line 545
I did a lot of googling, but can't seem to figure out what this error is talking about. Somebody suggested using forfiles.exe in order to get the #variables to work, but I tried that (along with the full forfiles path), and nothing seems to be working...
Can someone at least point me in the correct direction as to what this error message is telling me?

Just to see whether I could, I cobbled a little sumn sumn together to delete files older than 30 days old without using forfiles. Make sure the pushd line is set to go to the appropriate directory. I got the 2592000 by subtracting 01/01/2013 from 01/31/2013.
#echo off
setlocal enabledelayedexpansion
pushd "D:\SQL Database Back Ups\Update_FmlaManagement_Log"
set today=%date:~-10%
call :toEpoch %today%
set /a thirtyDaysAgo=%epoch% - 2592000
for /f "tokens=1,5*" %%I in ('dir /o:d *.txt ^| findstr "txt$"') do (
call :toEpoch %%I
if "%%K"=="" (set file=%%J) else (set file=%%J %%K)
if /i %thirtyDaysAgo% GTR !epoch! del /q "!file!"
)
popd
goto :EOF
:toEpoch date
echo wscript.echo datediff("s", "01/01/1970 00:00:00", "%1")>epoch.vbs
for /f %%x in ('cscript /nologo epoch.vbs') do set epoch=%%x
del /q epoch.vbs
goto :EOF
(VBscript borrowed from Cameron Oakenleaf.)
Admittedly, this won't work obsessively accurately. For instance, if a log file was last modified at noon 30 days ago and you're running this at 8:00 am, the file will probably be deleted even though it still has another 4 hours to go to reach 30 days old. And it's probably not nearly as efficient as forfiles.exe.
*shrug* It was a road less traveled and I traveled it.
EDIT: HerbCSO has another, probably better implementation that makes mine look like a Rube Goldberg-ian solution.

#file is only the File name. It does not include the path. If your batch file is not being executed within your path it will not see the file to delete it because you are in a different working directory.

I can't believe that the error comes from your sample line.
My forfiles (Win7) throws an error for the missing space between -p and the path.
And the text of the error message isn't normal for batch commands.
I don't know any batch command that tells you the line where an error occours, nor which parameter is wrong.
So I believe you got the error message from a completly different source.
Or you have a second forfiles command that do some totally other thing.
Or do you named one of your tests forfiles.bat?

Well, I'm not positive, but it seems the issue might have been a bad forfiles.exe from Microsoft's FTP server. I ended up downloading a second forfiles.exe (for Windows Server 2003) from this guy's site (direct download).
After replacing the original exe in C:\WINDOWS\system32 and getting rid of the copy in my downloads folder, I changed the syntax a little from the dashes to forward slashes as follows:
forfiles /p "D:\SQL Database Back Ups\Update_FmlaManagement_Log" /s /m *.txt /d -30 /c "cmd /c del #FILE"
and this worked perfectly first try!
So I guess the answer is, don't download forfile.exe from Microsoft's FTP server? :P
EDIT:
I would be very interested to know if other people have successfully used Microsoft's .exe in the link above? Otherwise maybe it's just something with my particular setup...

Related

Batch file loop - run all files that meet findstr criteria

Can someone advise where I have gotten wrong? I'm looking to run all files in a folder where the filename contains the word Expenses
cd /D Z:\System Administrator\System Backups\Scripts\
FINDSTR /S /M "expenses" *.*
FOR /F %%i in ('findstr /I /S /M "expenses" *.py') DO command %%i
findstr will get me the list of files I need, I just can't get them to run and get the error that command is not recognised as an internal or external command.
The list of files will be
Expenses 2017-18.py
Expenses 2018-19.py
etc
Thanks in advance
UPDATE
I have found that this works, although I welcome any improvements
for /R %%f in (*expenses*.py) do start python "%%f"
I believe that what is being sought is the instruction to actually execute the python files %%i. I'm no python expert - I don't know whether you need to simply use whatever.py from the prompt or somexecutablename whatever.py.
I believe that you'd probably need call "%%i" to run the files serially or, to run in parallel, use start "" "%%i". In either case, if you need somexecutablename then insert that before "%%i".
The empty string in the start version is the windowtitle. It's really needs to be there, even if empty - but you could replace it with "%%i" to show the executing filename as the window title.

Batch: Preserve (creation-)date on copying files to another (flatten) folder structure, incl. renaming files to avoid doublettes

this is my first question, so I apologize beforehand if I write not as you are used to...
fact:
I've a deep folder structure with tons of files (images,videos and so on) so I want to copy that files to a flat structure for a better overview.
I want to keep (at least) the original date attributes: creation-date and last-modified date.
Problem 1) there are files with same name 00001.jpg in different folders which I want to have in same folder, so I want to add creation date/time to filename on copy process.
00001.jpg becomes 2015-11-17_11-23-35_00001.jpg
So far so good. Or not good...
Copy and XCopy doesn't give me an option to do that, without loosing at least the creation date information (I didn`t find a solution with both).
Now I try to copy the files (file by file) with robocopy to new folder and use ren on the copied file to "pre-set" the date/time information before the filename.
Here is a simple test.bat example:
setlocal enableextensions enabledelayedexpansion
robocopy . ./zzz original.txt /copy:DATSO
pause
rem :: formatted creation date of original file will be here, in real life
set "myDate=2015-11-17-_11-23-35"
rem rename "./zzz/original.txt" "!myDate!_renamed.txt" ::doesnt work: why? relative path??
rem :: this will do what I want - original creation date is kept on copy file
FOR %%A IN (zzz/original.txt) DO REN "%%~fA" "!myDate!_%%~nxA"
[possibly] Problem2) Is there a better way to do this, or could I run into thread problems (asynchronous execution). Could it be, that I try to rename a file before the robocopy has finished the copy process (e.g. for large files)?
Sorry I'm a totally batch newbie (also as poster in SO ;).
ThanX in advance for each tip and also for critics on my solution approach. Maybe I have the horse-blinkers on my head and dont see the easy solution?!
[edit: formatting of post]
[edit: content of post -> date/time in front of filename for better sorting]
It is possible to use command DIR to get recursive listed all files in the specified folder and its subfolders with creation date/time.
The format of the date/time depends on Windows Region and Language settings.
Example output for F:\Temp\Test on my machine with English Windows 7 and region is configured to Germany on running the command line dir F:\Temp\Test\* /A-D /S /TC:
Volume in drive F is TEMP
Volume Serial Number is 1911-26A4
Directory of F:\Temp\Test
25.09.2017 17:26 465.950 SimpleFile.ccl
1 File(s) 465.950 bytes
Directory of F:\Temp\Test\Test Folder
25.09.2017 17:26 360.546 Test File.tmp
1 File(s) 360.546 bytes
Total Files Listed:
2 File(s) 826.496 bytes
0 Dir(s) 58.279.460.864 bytes free
This output is filtered with findstr /R /C:"^ Directory of" /C:"^[0123][0123456789]" to get only lines starting with  Directory of (note the space at begin) or with a number in range 00 to 39.
Directory of F:\Temp\Test
25.09.2017 17:26 465.950 SimpleFile.ccl
Directory of F:\Temp\Test\Test Folder
25.09.2017 17:26 360.546 Test File.tmp
And this filtered output is processed by FOR loop and the commands executed by FOR.
#echo off
for /F "tokens=1-2*" %%A in ('dir "F:\Temp\Test\*" /A-D /S /TC ^| %SystemRoot%\System32\findstr.exe /R /C:"^ Directory of" /C:"^[0123][0123456789]" 2^>nul') do (
if "%%A %%B" == "Directory of" (
set "FilePath=%%C"
) else (
set "CreationDate=%%A"
set "CreationTime=%%B"
for /F "tokens=1*" %%I in ("%%C") do set "FileName=%%J"
call :RenameFile
)
)
goto :EOF
:RenameFile
set "NewName=%CreationDate:~-4%-%CreationDate:~3,2%-%CreationDate:~0,2%_%CreationTime:~0,2%-%CreationTime:~3,2%_%FileName%"
ren "%FilePath%\%FileName%" "%NewName%"
goto :EOF
It would be advisable to put command echo before command ren in last but one line to first verify the expected new file names.
ren "F:\Temp\Test\SimpleFile.ccl" "2017-09-25_17-26_SimpleFile.ccl"
ren "F:\Temp\Test\Test Folder\Test File.tmp" "2017-09-25_17-26_Test File.tmp"
Note: The batch file must be in a folder not processed by this batch file as otherwise the batch file itself would be renamed while running which breaks the processing of the batch file.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
dir /?
echo /?
for /?
goto /?
if /?
ren /?
set /?
By the way: WinRAR can add files into a RAR archive with creation and last access time in addition to last modification time and extract the files to a different directory with restoring also creation and last access time using SetFileTime function of Windows kernel.
currently I use Locale independent date. I use tokens from that for currrent date/time.
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set datetime=%%I
rem :: format it to YYYY-MM-DD_hh-mm-ss
set myDateTime=%datetime:~0,4%-%datetime:~4,2%-%datetime:~6,2%_%datetime:~8,2%-%datetime:~10,2%-%datetime:~12,2%
Thats not the problem.
To clarify:
The listing is also not the problem.
I loop throw all related files without a prob (except batch files and output dir and its sub tree ;).
My problem is:
I call robocopy for each file, then I rename the file to save the original creation date. My fear is that it makes problems (Multi-Threading?) for large files and for the number of calls (many thousend times)
Is batch execution really serialized? Is the process waiting for robocopy, that it has finished, before I try to rename file. Could I run into dead-locks for vry large files? I'll test it with some fake gigabyte-files.
Your suggestion, to use winrar sounds interesting.
If I could add all that files to a big archive (with structure) and at the end extract it to target dir... I'll try it ;)
If it doesn't work I will program it in java!
There I know what to do, thats my playground :D
I thought it would be easy to write a simple batch file, to do this for me, but it seems it's not as easy as I thought!
ThanX anyway

Using robocopy with source and destination as variables

Completely new to scripting, tried to find a solution through searching the web but I'm stumped, so asking for help please!
I'm trying to use robocopy with a variable as both the source and destination, different one for each, but I just can't get the right syntax.
The hard code which I can get to work fine is:
robocopy C:\Users\me\Documents\a C:\Users\me\Documents\b
But I can't get it to work with variables. I've tried, after reading around, what seems like all variations of the below with " and % in/out, with and without Set, and none of them have worked.
Set src="C:\Users\me\Documents\a"
Set dest="C:\Users\me\Documents\b"
robocopy %src% %dest%
Hope that's a clear explanation of what I'm trying to do, if not ask for clarification.
Thanks in advance for any help.
set "src=C:\Users\me\Documents\a"
set "dest=C:\Users\me\Documents\b"
robocopy "%src%" "%dest%"
Nothing bad with your sintax. This way is "more robust" or more standard or more habitual, ...
BUT robocopy is not copy not xcopy. You are asking robocopy to copy from source to target changed or new files. If there are no changes, robocopy will not copy anything. If you have tried and it worked, .... if no changes, no file copy.
AND you have not asked robocopy to copy subdirectories. So, if there are no files in source directory, nothing will be copied.
I have found Robocopy is touchy to the point of being arbitrary about syntax. I have found a similar problem to yours:
This code works:
Set Today=%DATE:~0,3%
Robocopy "G:\folder A" "U:\%Today%\folder A" ^
/S /XJD /R:25 /W:4 /NP /copyall ^
/LOG:"U:\%Today%\FolderALog.txt"
IF ERRORLEVEL 8 goto Badend
This (nicely structured) code doesn't work
Set Today=%DATE:~0,3%
Set source="G:\folder A"
Set target="U:\%Today%\folder A"
Set Logname="U:\%Today%\FolderALog.txt"
Echo Source is %Source%
Echo Target is %Target%
Echo logfile named %Logname%
Pause
Robocopy %source% %target% ^
/S /XJD /R:25 /W:4 /NP /copyall ^
/LOG:%Logname%
Pause
However, in this 2nd example, take the 1st continuation out of the command line and it works:
Set Today=%DATE:~0,3%
Set source="G:\folder A"
Set target="U:\%Today%\folder A"
Set Logname="U:\%Today%\FolderALog.txt"
Echo Source is %Source%
Echo Target is %Target%
Echo logfile named %Logname%
Pause
Robocopy %source% %target% /S /XJD /R:25 /W:4 /NP /copyall ^
/LOG:%Logname%
Pause
I've been using the caret (^) as a continuation character in batch command jobs ever since the DOS days, but in this instance the parser tries to concatenate it with the previous variable and the job dies because the system thinks I'm trying to name a folder "U:\%Today%\folder A ^". So goes it -- you keep trying things until something works.
Troubleshooting techniques: Doing Echos of newly defined variables then pausing allows you to check for typos and misplaced quote marks. The pause at the end gives you ample time to read the error code, should there be one. Another thing I ran into once was inadvertently inserting an unprintable character in place of a space in a path enclosed with quotes.
RoboCopy is very powerful and well worth occasional tinkering with touchy syntax.
Looks like an old question, but I ran into this issue myself today and solved it by using double slashes for the set command:
Set src="C:\\Users\\me\\Documents\\a"
Set dest="C:\\Users\\me\\Documents\\b"
robocopy %src% %dest%
Try this way
Set src=C:\Users\me\Documents\a
Set dest=C:\Users\me\Documents\b
robocopy %src% %dest% /E
/E - for copying of Subfolder including empty subfolder
If you are trying to use a .bat the code will be like this:
Set src="C:\Users\me\Documents\a"
Set dest="C:\Users\me\Documents\b"
robocopy.exe %src% %dest%
You forgot to put the .exe
dude try the XCOPY command it will work for sure!
example:
xcopy "C:\Users\me\Documents\a" "C:\Users\me\Documents\b"
it will ask is the destination is a folder or a file, so once u chose folder (dir) it will copy!
hope it helps! :D

Locate and Delete Folder(s) with Command Prompt

At work we handle people every day who wants help regarding signing on to their Online Bank from home. Some times we need the user to delete files and guiding them to do this, can be tiresome and bothersome a lot of the time, wasting upwards to 20 minutes because the user is inexperienced in computers.
We have been talking about a solution (if possible) where we let the user download a batch file that we tell them to run, which can then delete the required files for us. I ask this question here, because none of us here at work, have experience with batch files.
Personally I've played around with it from time to time but I can't really come up with a solution that fits our needs and when I search around on the net, I can't find a solution that fits either. The script would have to locate the folder automatically (if possible).
Is this possible?
Would you be able to help me accomplish this?
Thanks in advance!
Maybe this could help you, I commented it so you understand what it is doing ;)
:: Program to remove Folders which fullfill the criterias
:: You won't see the commands in the console
#echo off
:: Go to drive C (i think you'll need application data or similar and this is
:: on c, but if the bat is started in an other partition, it will search the
:: one he starts in
C:
:: Go to the path in which you'll search, if you want C:\ , remove this
CD "C:\yoursearchstartpath"
:: Okay, this is the loop, it gets all folders ( /A -D is for folders)
:: which have delMe in their name and then asks if you want to delete it
:: showing the path to make sure you don't delete sth accidentially
for /f "delims=" %%a IN ('dir /S /B /A -D *delMe*') do RD /S "%%a"
:: That the batch file is not closed automatically but shows that it's finished
set /p id="Finished, press Space to quit " %=%
A simple one:
rd /s "%USERPROFILE%\.oces2"
If they follow a pattern (e.g. start with .oces):
#echo off
cd /d "%USERPROFILE%"
for /d %%i in (.oces*) do rd /s "%%i"
pause
Check out this link
http://support.microsoft.com/kb/65994
I created a sample batch file A.BAT. It checks if the C:\Folder\F1 exists, and removed the folder F1 if available
IF EXIST D:\FOLDER\F1 GOTO A
EXIT
:A
D:
DEL D:\FOLDER\F1\*.*
RMDIR F1
Hope it helps

Delete sub directories older than 30 days

I'm trying to create a batch script that will delete all sub directories which are older than 30 days.
I'm really new to batch scripting so I'm just hoping that someone can help me out on this.
I was able to find a script that delete all sub directories in specified location.
#for /f "tokens=*" %%a in ('dir /s /b "C:/temp/test" 2^>NUL') do rd /s /q "%%a"
Can someone tweak this script so it deletes only directories which are 30 days old?
I think FORFILES is going to do it...
FORFILES -D 30 will iterate all files last modified over 30 days ago
So, something like...
FORFILES /S /D -30 /C "cmd /c IF #isdir == TRUE rd #path"
Should (untested) recursively remove all folders older than 30 days :)
Btw - Check out http://ss64.com/nt/ for more command line goodness
This is working fine for me:
Posted by Matt Roberts --> FORFILES /S /D -30 /C "cmd /c IF #isdir == TRUE rd #path"
Be careful when you start the ".bat" file with "Run as administrator", it's not using the current location of the file it takes this location --> "C:\Windows\system32"
For savety reasons add the /P "C:\temp"
FORFILES /P C:\temp /S /D -30 /C "cmd /c IF #isdir == TRUE rd #path"
Assuming you are restricted to batch files... check this - but if you can use VBScript, I think you can do a bit better.
Now that you have clarified your real problem, please understand that if you meant to use System.exec() you will have to contend with plenty of drawbacks.
Alternatively if you really want to use JNDI (you mention "native" but don't make clear what you mean) maybe this will be of help: http://mindprod.com/products1.html#FILETIMES
Do you have powershell on your system?
dir | ? { $_.LastWriteTime -lt [DateTime]::Now.AddDays(-30) } | % { rm $_.FullName }
I know this is an older topic; however, I was recently looking to do this and was able to by building off of what Matt Roberts suggested. I used the following FORFILES syntax:
FORFILES /P \path\to\dir /S /C "cmd /c IF #isdir == TRUE rmdir /S #path /Q" -D -30
You will need to replace \path\to\dir with the path (including drive letter) to the directory (/P) you want to run this on. This will then recursively (/S) search through the directory and run (/C) rmdir (again recursively). Without /Q you are asked if you want to delete each dir/file so if you are planning on running this silently in a script you will need to have it. You can change the amount of days (-D) by changing -30 to something else.
I then used Task Scheduler to automate this once every week (confirmed working). To make sure it works, set the task with 'run with highest privileges'
Note: This setup will irrevocably delete the files. They will not appear in your recycle bin. So once they are gone they're gone (unless you have backups).
You might want to consider using Windows Script Host, in which you could run a VBScript to do just that. Think of it like a batch file with more flexibility and power.
See http://www.computing.net/answers/programming/wsh-delete-files-in-folder-by-date/16255.html
This is not going to be a simple tweak. As it stands, there is no easy way (that I know of) to do the date-diff operation in the cmd interpreter.
First you'll have to parse the current date:
C:\>date /T
Thu 08/05/2010
Once you have the day, month, year, you have to get the date for each item in the directory listing, which you can do by removing the /b param in the dir command and modifying the tokens line to give you tokens 1 and 4, i.e. tokens=1,4, and then doing the date math yourself, which will be a pain because you have to handle different lenght months, and December -> January transitions (new years), etc, and you're almost certain to get it wrong.
Also add the /ad param to get just directories.
I would recommend using PowerShell or some other scripting technology that gives you the tools you need to manipulate dates.

Resources