I am trying to connect to a network drive, copy a file and move it to another location, and log if it is successful or not. This is what I got so far:
#echo off
#setlocal enableextensions enabledelayedexpansion
if exist Transfer_logfile.txt (
ECHO Y | del Transfer_logfile.txt
)
set LogFile=_logfile.txt
set logg=^> _^&^& type _^&^&type _^>^>%LogFile%
for /F "tokens=*" %%A in (ipaddresses.txt) do (
net use \\%%A\c$\test /USER:test %logg%
echo copying files across to %%A... %logg%
COPY -f -R -Y C:\test\test.exe \\%%A\c$\test\test.exe %logg%
echo Copy completed.. %logg%
net use \\%%A\c$\test /delete /Y %logg%
)
pause
Any help on how to finish this of would be appreciated.
I am struggling to save any errors in the output. If it errors I want it to just save that it failed in output and go on to the next IP in the IP address text file.
I think, I need to wrap an if around the net use checking that the ip address pings first. However this does not work.
#echo off
#setlocal enableextensions enabledelayedexpansion
if exist Transfer_logfile.txt (
ECHO Y | del Transfer_logfile.txt
)
set LogFile=_logfile.txt
set logg=^> _^&^& type _^&^&type _^>^>%LogFile%
for /F "tokens=*" %%A in (ipaddresses.txt) do (
ping -n %%A > NUL
IF ERRORLEVEL 0 (
echo
ELSE goto :skipcopyhost1
net use \\%%A\c$\test %logg%
echo copying files across to %%A... %logg%
COPY -f -R -Y C:\test\test.exe \\%%A\c$\test\test.exe %logg%
echo Copy completed.. %logg%
net use \\%%A\c$\test /delete /Y %logg%
)
pause
Try this not tested batch code:
#echo off
if not exist ipaddresses.txt goto :EOF
setlocal
del /F Transfer_logfile.txt 2>nul
set "LogFile=Transfer_logfile.txt"
for /F %%A in (ipaddresses.txt) do (
%SystemRoot%\System32\ping.exe -n %%A >nul
if errorlevel 1 (
echo %%A is not available in network.>>%LogFile%
) else (
echo Connecting to %%A ...>>%LogFile%
%SystemRoot%\System32\net.exe use X: \\%%A\c$\test /persistent:no /Y 2>&1 >>%LogFile%
echo Copying file to %%A ...>>%LogFile%
copy /B /V /Y C:\test\test.exe X:\test.exe 2>&1 >>%LogFile%
echo Disconnecting from %%A ...>>%LogFile%
%SystemRoot%\System32\net.exe use X: /delete /Y 2>&1 >>%LogFile%
)
echo.>>%LogFile%
)
endlocal
pause
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.
copy /?
del /?
for /?
goto /?
if /?
net /?
net use /?
set /?
Further read the Microsoft articles:
Using Command Redirection Operators
Testing for a Specific Error Level in Batch Files
I don't explain all the errors in your code as they are too many.
Related
I am running a script that goes through network folders and saves the found files, however it is taking too long to run. I have tried isolating the findstr to a single folder and it runs at an okay time, so I assume it has something to do with the FOR loop.
#echo off
setlocal
set SERVERS=server1 server2 server3 server4
cls
echo Type below the query parameters:
set /p year=Year (4 digits):
set /p month=Month (2 digits):
set /p day=Day (2 digits):
set /p query=Query string:
cls
echo Results:
del /F /Q "C:\Users\%USERNAME%\Desktop\found_files\*" 2>nul
if not exist "C:\Users\%USERNAME%\Desktop\found_files" mkdir "C:\Users\%USERNAME%\Desktop\found_files"
for /f "tokens=*" %%a in ('for %%i in ^(%SERVERS%^) do #findstr /S /I /M /C:"%query%" "\\%%i\folder_structure\*%year%-%month%-%day%*.xml"') do copy /Y "%%a" "C:\Users\%USERNAME%\Desktop\found_files" >nul & echo %%a & set found=1
echo.
if "%found%"=="1" (
echo File^(s^) saved successfully!
) else (
echo No files found!
)
echo.
pause
if "%found%"=="1" explorer C:\Users\%USERNAME%\Desktop\found_files
Your script is already optimized pretty well. I don't think there is much you can do to speed things up.
I suspect your problem is that FINDSTR is running on your local machine, and it must scan the files on all UNC paths (almost surely not local). This means the entire content of every file must be transmitted across your network. If your system is anything like where I work, that could be a nightmare. Our network drive performance is pathetic (more than a factor of 100 slower than local drive)!
Squashman (and SomethingDark) were somewhat concerned about your outer FOR /F executing a nested FOR statement. But I believe that is the most efficient way. When FOR /F iterates command output, it must launch a new process to execute the command. Your current script only needs one sub-process.
The more "traditional" approach would be to move the %SERVERS% iteration outside the inner loop as follows:
for %%i in (%SERVERS%) do for /f "tokens=*" %%a in (
'findstr /S /I /M /C:"%query%" "\\%%i\folder_structure\*%year%-%month%-%day%*.xml"'
) do copy /Y "%%a" "C:\Users\%USERNAME%\Desktop\found_files" >nul & echo %%a & set found=1
But this is actually less efficient because it must launch a new sub-process for each UNC path within %SERVERS%. That being said, I don't think the difference is significant compared to the actual bottle neck of transmitting the file content across the network.
To show the impact of one vs. 100 sub-processes, I ran a quick comparison of the following logically equivalent (but meaningless) commands:
for /f "delims=" %%F in (
'for /l %%N in ^(1 1 100^) do #findstr /m "^" *'
) do echo %%F>nul
:: This took 39 seconds on my machine
for /l %%N in (1 1 100) do for /f %%F in (
'findstr /m "^" *'
) do echo %%F>nul
:: This took 60.9 seconds on my machine
#echo off
set SERVERS=server1,server2,server3,server4
cls
echo Type below the query parameters:
:: Type echo %date% on command prompt if its returns the current date dd/mm/yyyy format, you can load the variables using a substring:
set year=%date:~6,4%
set month=%date:~3,2%
set day=%date:~0,2%
set /p query=Query string:
:: set counter for files founded
set found=0
cls
echo Results:
if not exist "C:\Users\%USERNAME%\Desktop\found_files" (mkdir "C:\Users\%USERNAME%\Desktop\found_files") else (del /F /Q "C:\Users\%USERNAME%\Desktop\found_files\*" 2>nul)
for /f %%i in (%SERVERS%) do ('#find /i /c "%query%" "\\%%i\folder_structure\*%year%-%month%-%day%*.xml"') do (
if "%%i"=="1" (set /a found=%found%+1 && copy /Y "\\%%i\folder_structure\*%year%-%month%-%day%*.xml" "C:\Users\%USERNAME%\Desktop\found_files" >nul && echo File^(s^) saved successfully! & echo.) else (echo No files found!)
)
echo.
pause
if %found% gtr 0 (explorer C:\Users\%USERNAME%\Desktop\found_files)
I have a problem with the batch script below when checking the write permissions on the target folders.
It works well if there are only write-protected folders. But if there are a mix of write-protected folders and non-write-protected folders, it will also run xcopy for the write-protected folders.
I think it has to do with the value assigned to "write_ok" that always keeps the last value.
But how can I fix it ?
Here is my code :
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set BackupDest=D:\backup
for /f "tokens=*" %%I in ('dir /a:d-h /b "%HomeDrive%\users\*" ^| findstr /x /i /l /v /g:"%~dp0exclude_users.txt"') do if exist "%BackupDest%\%%I\" (
echo -----------------------------------------
echo Processing user : %%I
echo -----------------------------------------
echo
:: checking write permissions
copy /y nul "%BackupDest%\%%I\.writable" >nul 2>&1 && set write_ok=1
if defined write_ok (
del "%BackupDest%\%%I\.writable"
xcopy "%%I\Desktop" "%BackupDest%\%%I\Desktop\" /e /i /y
xcopy "%%I\Documents" "%BackupDest%\%%I\Documents\" /e /i /y
) else (
echo Access refused ^(check permissions^)
)
)
pause
exit
Thank you for your help.
You forgot to unset the write_ok variable, so after once it's set, it is always defined.
Just unset it before using it:
:: checking write permissions
set "write_ok="
copy /y nul "%BackupDest%\%%I\.writable" >nul 2>&1 && set write_ok=1
if defined write_ok (
del "%BackupDest%\%%I\.writable"
xcopy "%%I\Desktop" "%BackupDest%\%%I\Desktop\" /e /i /y
xcopy "%%I\Documents" "%BackupDest%\%%I\Documents\" /e /i /y
) else (
echo Access refused ^(check permissions^)
)
Alternatively you can avoid the variable completely:
:: checking write permissions
copy /y nul "%BackupDest%\%%I\.writable" >nul 2>&1 && (
del "%BackupDest%\%%I\.writable"
xcopy "%%I\Desktop" "%BackupDest%\%%I\Desktop\" /e /i /y
xcopy "%%I\Documents" "%BackupDest%\%%I\Documents\" /e /i /y
) || (
echo Access refused ^(check permissions^)
)
I have differents files, and I want to check for any changes in any of them, using batch. This is what I have:
#echo off
setlocal enableDelayedExpansion
set "list=test.txt test1.txt"
:loop
timeout -t 1 >nul
for %%j in (%list%) do (
REM Here only prints test.txt
echo %%j
for %%i in (%%j) do echo %%~ai|find "a">nul || goto :loop
echo file was changed %%j
attrib -a %%j
)
goto :loop
If I use only one file, works, but not with two or more. The idea is, that echo file was changed %%j only outputs the correct file, and not both.
Any ideas?
EDIT:
If I do some changes:
#echo off
title LAN chat reader
setlocal enableDelayedExpansion
set "list=test.txt test1.txt"
:loop
timeout -t 1 >nul
for %%j in (%list%) do (
echo %%j
echo %%~aj|find "a">nul || goto :loop
echo file was changed %%j
attrib -a %%j
)
goto :loop
works, but only alerts me the changes in the second file, after I make changes in the first. I can understand that the problem is in the loop, so there is where I'm confused.
I'd suggest a couple of things.
1: Use
call :CheckFile "%%j"
instead of a nested for loop - makes things easier to read.
2: you can use DIR to check the attribute a bit more directly:
dir /aa %%j > nul 2>&1 && attrib -a %%j
Both together looks something like:
:loop
timeout -t 1 >nul
for %%j in (%list%) do call :CheckFile "%%j"
goto :loop
:CheckFile
echo %1
dir /aa %1 > nul 2>&1 || goto :EOF
echo file was changed %1
attrib -a %1
goto :EOF
I on windows 8.1. I get USB with hidden file/folders. To unhide them I use attrib command . I want to run the commands by simply inserting the USB. Pl help.
echo off
echo Please have patience!!! Wait or Minimise the window!!!
rem c:\script\unhide.bat
#echo off
for /F "usebackq tokens=1,2,3,4 " %%i in (`wmic logicaldisk get caption^,description^,drivetype 2^>NUL`) do (
if %%l equ 2 (
echo %%i is a USB drive.
)
)
Pause
Here I got the drive letter H. I am unable to use drive letter and use the following commands in USB. How can is I run below commands in USB. I mean Change Drive, run attrib command in USB, delete unwanted files from USB and see USB's contents.
cd\
attrib -s -h -r /s /d
del *.lnk
del thumbs.db
del desktop.ini
del autorun.inf
echo Your Folders has been recovered!!! Check your folders and files
dir
pause
exit
#ECHO OFF
SETLOCAL enableextensions
echo Please have patience!!! Wait or Minimise the window!!!
rem c:\script\unhide.bat
for /F "skip=1 tokens=1-3" %%i in ('
wmic logicaldisk where "drivetype=2" get caption^,drivetype^,SystemName
') do (
if "%%j"=="2" (
echo "%%i" is a USB drive ^(DriveType=%%j^).
pushd "%%i\"
SETLOCAL enabledelayedexpansion
echo current folder !CD!
ENDLOCAL
echo attrib -H -S -T /S /D /L >NUL 2>&1
echo del *.lnk 2>NUL
echo del thumbs.db 2>NUL
echo del desktop.ini 2>NUL
echo del autorun.inf 2>NUL
echo Your Folders has been recovered!!! Check your folders and files
dir
pause
popd
)
)
ENDLOCAL
goto :eof
Note:
wmic command changed as follows:
where clause;
description omitted as this property vary in word number and therefore breaks the tokenization;
always non-empty property SystemName appended to pass over the ending carriage return in the line returned: wmic behaviour = each output line ends with 0x0D0D0A (<CR><CR><LF>) instead of common 0x0D0A (<CR><LF>). For another (general) approach see Dave Benham's WMIC and FOR /F: A fix for the trailing <CR> problem;
for /F loop adapted according to altered wmic command (and skip=1);
operational attrib -H -S -T /S /D /L is merely echoed for debugging purposes; remove echo no sooner than debugged (the same for all del commands);
used pushd - popd pair: PUSHD changes the current directory/folder and stores the previous folder/path for use by the POPD command;
folder System Volume Information should keep attributes System & Hidden if present.
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
)
)