I have a somewhat related, but different questions here.
I have a batch script (*.bat file) such as this:
#ftp -i -s:"%~f0"&GOTO:EOF
open ftp.myhost.com
myuser
mypassword
!:--- FTP commands below here ---
lcd "C:\myfolder"
cd /testdir
binary
put "myfile.zip"
disconnect
bye
Basically this is a script that uploads a zip file to a ftp site. My question is that, the upload operation can fail from time to time ( the remote ftp is not available, "myfile.zip" is non-existent, upload operation interrupted and whatnot), and when such unfortunate things happen, I want my bat file return 1 ( exit 1).
It would be great if my upload wasn't successful, the ftp would throw an exception ( yes, like exception in C++), and I would have a catch-all exception that catches it and then exit 1, but I don' think this is available in batch script.
What is the best way to do what I need here?
You can redirect the output to a log file and when the ftp session is finished the file can be parsed.
#ftp -i -s:"%~f0" > log.txt & GOTO :parse
open ftp.myhost.com
myuser
mypassword
!:--- FTP commands below here ---
lcd "C:\myfolder"
cd /testdir
binary
put "myfile.zip"
disconnect
bye
:parse
for /F "delims=" %%L in (log.txt) Do (
... parse each line
)
Windows FTP does not return any codes.
I suggest running a batch file that echo your ftp commands to a input response file, then use this file as input to the ftp command, redirecting stderr to a file and verifying the file size. something like this
echo open ftp.myhost.com >ftpscript.txt
echo myuser >>ftpscript.txt
echo mypassword >>ftpscript.txt
echo lcd "C:\myfolder" >>ftpscript.txt
echo cd /testdir >>ftpscript.txt
echo binary >>ftpscript.txt
echo put "myfile.zip" >>ftpscript.txt
echo disconnect >>ftpscript.txt
echo bye >>ftpscript.txt
ftp -i -s:ftpscript.txt >ftpstdout.txt 2>ftpstderr.txt
rem check the ftp error file size, if 0 bytes in length then there was no erros
forfiles /p . /m ftpstderr.txt /c "cmd /c if #fsize EQU 0 del /q ftpstderr.txt"
if EXIST ftpstderr.txt (
exit 1
)
Your only option in batch files that I know of is to use the "IF ERRORLEVEL" syntax, which requires your ftp client to return a non-zero error code.
http://www.robvanderwoude.com/errorlevel.php is a good reference guide.
Unfortunately I do not if the standard Windows ftp client returns non-zero error codes, so you may have to code your own if this is a requirement. This link suggests that it does not return an error code, but provides a work around albeit clunky, by redirecting the output to a file and using the FIND command to return an error code.
Related
I'm trying to upload latest files generated in one hour to a remote server. But the script I wrote is intelligent enough to gather only the latest file in directory and upload it to FTP. Any chance of set the variable type as array and upload the files in the array?
My FTP batch file:
FOR /F %%I IN ('DIR "abcdef*.bac" /B /O:D') DO SET latest_file=%%I
echo user domain/username> ftp.txt
echo password>> ftp.txt
echo cd remotepath>> ftp.txt
echo put %latest_file%>>ftp.txt
echo quit>> ftp.txt
ftp -n -s ftp.txt Servername>ftp_logs.txt
del ftp.txt
It would be difficult to write this in a pure batch file code.
You better use some more powerful tool.
For example with WinSCP FTP client, it's trivial:
winscp.com /ini=nul /log=upload.log /command ^
"open ftp://username:password#ftp.example.com/" ^
"put -filemask=>1H C:\local\path\abcdef*.bac /remote/path/" ^
"exit"
References:
Automate file transfers to FTP server with WinSCP;
Converting Windows FTP script to WinSCP script;
File masks with time constraints.
(I'm the author of WinSCP)
I'm writing a batch script for a Windows 7 machine. The goal of the script is to move files from the directory C:\directory\source_dir\ to an ftp server ftpserver.domain.com.
Not all the files should be uploaded to the ftp server, so I'm using regular expression.
File Structure:
C:\directory\source_dir\TF_directory1
C:\directory\source_dir\TF_directory1\file1.txt
C:\directory\source_dir\TF_directory1\file2.txt
C:\directory\source_dir\TF_directory1\sub_dir\file_A.txt
C:\directory\source_dir\Ignore_directory\not_important.txt
C:\directory\source_dir\TF_123.CAM555.abc
C:\directory\source_dir\TF_123.CAM123.zyx
C:\directory\source_dir\TF_987.CAM555.abc
C:\directory\source_dir\wrong_file.txt
From the above structure TF_directory1 and everything inside should be uploaded. As should the files TF_123.CAM555.abc, TF_123.CAM123.zyx and TF_987.CAM555.abc.
Here's my problem:
The ftp put command returns an error on the directory
connected to ftpserver.domain.com
220 Welcome to the ftp server
ftp> user USERNAME
331 Please specify the password
---> PASS PASSWORD
230 Login successful.
ftp>
ftp> cd new_files
250 Directory successfully changed.
---> CWD new_files
ftp> put C:\directory\source_dir\"TF_123.CAM555.abc"
---> PORT 10,X,X,X,4,240
200 PORT command successful. Consider using PASV.
---> STOR TF_123.CAM555.abc
150 Ok to send data.
226 File receive OK.
ftp> put C:\directory\source_dir\TF_123.CAM123.zyx"
---> PORT 10,X,X,X,4,240
200 PORT command successful. Consider using PASV.
---> STOR TF_123.CAM555.abc
150 Ok to send data.
226 File receive OK.
ftp> put C:\directory\source_dir\TF_987.CAM555.abc"
---> PORT 10,X,X,X,4,240
200 PORT command successful. Consider using PASV.
---> STOR TF_123.CAM555.abc
150 Ok to send data.
226 File receive OK.
ftp> put C:\directory\source_dir\"TF_directory1"
**Error opening local file C:\directory\source_dir\TF_directory1.**
ftp> quit
---> QUIT
221 Goodbye.
Script:
set base_dir=C:\directory\
set log_dir=%base_dir%source_dir\
set log_file=%base_dir%log_file.txt
::Function to check if the ftpinfo exists. If not, create it.
:createFTPinfoFile
echo ########################## entering function :createFTPinfoFile
if not exist %base_dir%ftpinfo.dat (
echo %timestamp% -- Creating ftpinfo.dat file at location %base_dir% >> %log_file%
echo user USERNAME> %base_dir%ftpinfo.dat
echo PASSWORD>> %base_dir%ftpinfo.dat
echo %timestamp% -- Created ftpinfo.dat >> %log_file%
) ELSE (
echo %timestamp% -- %base_dir%ftpinfo.dat was not properly removed - Removing the file >> %log_file%
del %base_dir%ftpinfo.dat
echo %timestamp% -- Creating ftpinfo.dat file at location %base_dir% >> %log_file%
echo user USERNAME> %base_dir%ftpinfo.dat
echo PASSWORD >> %base_dir%ftpinfo.dat
echo %timestamp% -- Created ftpinfo.dat >> %log_file%
)
echo ############################ finished :createFTPinfoFile
EXIT /B 0
:addFilesToFTPinfo
echo ############################ entering function :addFilesToFTPinfo
set num=0
echo %timestamp% -- Starting to add files from %log_dir% to ftpinfo.dat >> %log_file%
for /f "delims=" %%i in ('forfiles /p %log_dir% /m "TF_*.CAM*.*" /d -0 -c "cmd /c echo put %log_dir%#file >> %base_dir%ftpinfo.dat & echo 1" ^| find /c /v ""') do set /a num=%%i-1
echo %timestamp% -- Starting to add folders from %log_dir% to fptinfo.dat >> %log_file%
for /f "delims=" %%i in ('forfiles /p %log_dir% /m "TF_*" /d -0 /c "cmd /c if #isdir==TRUE echo put %log_dir%#file >> %base_dir%ftpinfo.dat & echo 1" ^| find /c /v ""') do set /a num=%num%+%%i-1
echo %timestamp% -- added everything to ftpinfo.dat >> %log_file%
echo ############################ finished :addFilesToFTPinfo
EXIT /B 0
REM::This function creates the connection to the ftp server using the information from ftpinfo.dat
:ftpUploadFiles
echo ########################## entering function :ftpUploadFiles
if exist %base_dir%ftpinfo.dat (
echo cd new_files >> %base_dir%ftpinfo.dat
CALL :addFilesToFTPinfo
echo quit >> %base_dir%ftpinfo.dat
echo %timestamp% -- Connecting to FTP server to upload files >> %log_file%
ftp -n -s:%base_dir%ftpinfo.dat ftpserver.domain.com
)
echo ########################## finished :ftpUploadFiles
EXIT /B 0
Does anyone know a better way to do this?
The Windows command-line ftp.exe client does not support recursive operations.
If you want to transfer folders, you have three options:
Do all the hard work in the batch file, generating ftp upload commands for all files and folders. While doeable, this is pretty difficult to implement.
Use an ad-hoc solution for your specific folder(s), like the answer by #SamDenty shows.
Easiest is to use a 3rd party command-line FTP client. Most 3rd party FTP clients do support recursive operations.
For example with WinSCP FTP client, you can use a script like:
open ftp://username:password#ftp.example.com/
put TF_directory1
put TF_123.CAM555.abc
put TF_123.CAM123.zyx
put TF_987.CAM555.abc
exit
And run the script (ftp.txt) from a batch file like:
winscp.com /script=ftp.txt
See the guide for converting Windows FTP script to WinSCP script.
(I'm the author of WinSCP)
You are using put to transfer a folder, but put doesn't support transferring folders, only files as stated by:
**Error opening local file C:\directory\source_dir\TF_directory1**
Instead of using put, try using:
mkdir TF_directory1
cd TF_directory1
mput C:\directory\source_dir\TF_directory1\*
Which would:
Make a directory on the FTP server named TF_directory1
CD into the directory
Copy all files from the TF_directory1 and place them in the new FTP folder
Reference -
Superuser
I would like to upload a file to my ftp server if internet is connected
In each run, i prefer:
if (ftp server can be connected){
upload the file "C:\abc.txt" to the ftp server directory "/ABC_DB"
}
Thus, I am not sure how to check ftp connection, is it possible to run like this:
echo abc > C:\abc.txt
???Check the connection here
OPEN your.ftp.server.com
usernameabc
passwordbcd
CD /ABC_DB
PUT "C:\abc.txt"
QUIT
PAUSE
Sorry for asking such silly question, but I am new in batch, hope u can help me =[
Test this: change lines 2,3,4 with your details
#echo off
set "name=your_ftp_user-name"
set "password=your_ftp_password"
set "server=ftp_server_name"
ping %server% |find /i "TTL=" >nul || (echo server offline, aborting&pause&goto :EOF)
set "ftpScript=%temp%\%~nx0.ftp.tmp"
(
echo open %server%
echo %name%
echo %password%
echo bin
echo CD /ABC_DB
echo PUT "C:\abc.txt"
echo quit
) > "%ftpScript%"
ftp -i -s:"%ftpScript%"
del "%ftpScript%"
I want to find if a file exists at FTP using if-exist filename -else statement using FTP batch script which is as follows:
ftp.txt open ftp.mysite.com
ftp.txt username
ftp.txt password
ftp.txt if exist filename (echo file exists) else (echo file doesn't exist)
ftp.txt quit
ftp -s:ftp.txt
the if-exist line above does not work.
Is there any other way to search?
Don't do the logic in the FTP script.
Call the ftp.txt script from a batch file. Within your ftp.txt script, just do a GET on your file. If the file is there, it'll be downloaded to the local directory. Otherwise, it won't. After calling the FTP script, check the file's existence in your local directory using standard DOS batch commands, i.e.:
#echo off
:FETCHFILE
ftp -s:ftp.txt
IF EXIST filetocheckfor.txt (
REM the file was there, so do something
) ELSE
echo Trying again...
REM ping "sleep" would go here
GOTO FETCHFILE
)
If you want to build a delay into your retries, perform a "sleep" by pinging a bogus IP address, as described in this post:
http://www.dullsharpness.com/2010/06/14/elapsed-timer-using-pure-ms-dos/
I need to write a single dos script which will first FTP from a remote server to my local directory and then will copy these files to another folder within the local machine. The reason behind the second step is that the destination folder path is based on whether the SYSTEM Processor of 32-bit or 64-bit.
I have two separate scripts which are working fine now. But when I am putting them together in a single script, it is failing with the ftp command prompt. Here is the script which I am using -
#echo off
:MAIN
SETLOCAL ENABLEDELAYEDEXPANSION
set winver=%PROCESSOR_ARCHITECTURE%
rmdir c:\batch\temp
mkdir c:\batch\temp
goto :ftpbegin
:ftpbegin
#ftp -i -s:"%~f0"&GOTO:EOF
open x.y.z.a
<userid>
<password>
!:-----FTP commands here -----
lcd C:\batch\temp
cd CGServices\Uploads
binary
mget "*.psl"
mget "*.PST"
mget "*.psy"
get abc.ini
get def.pmd
disconnect
bye
:eof
exit /b
:findwin
if %winver% ==x86 (goto :copywin32) else (goto :copywin64)
:copywin32
echo "inside copywin32"
<do the copy files here>
:copywin64
<do copy files here>
exit /b 0
However, the ftp script seems to cause a break while executing the second part of my program since it is calling the program in a loop in ftp prompt. So, none of the dos commands are translated on FTP prompt.
Any help on how to achieve this in a single script for this is highly appreciated.
thanks,
Sanders
The FTP command AFAIK cannot process the commands from the command line without reading the ftp commands from an external file. I usually download a windows version of wget, and it works well for us, perhaps you would like to have a look at that.
Here is the manual for wget http://www.editcorp.com/Personal/Lars_Appel/wget/v1/wget_7.html
for example
wget ftp://<user>:<password>#server.com/upload/file.ext
After invoking ftp command you tell your script to jump to ':EOF'. You can not use :EOF label for jumping inside a batch file. Goto :EOF basically means "jump to the end of the file", which is generally the same as calling exit /b. You can also call goto :EOF from inside a subroutine. In this case it mean "this is the end of the subroutine". For more info, see goto /? and call /?
Because in ftp.exe you are using your .bat file as a ftp command script, all the lines before open x.y.z.a will give you invalid command messages, so it would be good to minimize the number of lines before FTP command block.
Your script should look like this:
#echo off
goto main
:ftpbegin
#ftp -i -s:"%~f0" & goto ftpend
open x.y.z.a
<userid>
<password>
!:-----FTP commands here -----
lcd C:\batch\temp
cd CGServices\Uploads
binary
mget "*.psl"
mget "*.PST"
mget "*.psy"
get abc.ini
get def.pmd
disconnect
bye
:main
SETLOCAL ENABLEDELAYEDEXPANSION
set winver=%PROCESSOR_ARCHITECTURE%
rmdir c:\batch\temp
mkdir c:\batch\temp
goto ftpbegin
:ftpend
if not "%winver%"=="x86" goto copywin64
REM did not jump, so this is a 32-bit system
echo "inside copywin32"
<do copy files here>
goto finish
:copywin64
echo "inside copywin64"
<do copy files here>
:finish
endlocal