My requirement is to check if the file exists in a folder only when case matches the search.
I have searched the internet, also the basic command prompt help guide. I have no accurate answer. However, in the StackOverflow post: REF-Post the solution is provided by sending FileName as a variable to batch file. However, I would like to search the file by not using any variable sent to the Batch file.
#echo off
dir /b /a-d "%~1"|find "%~1" >nul
if %errorlevel% == 0 (echo found) else (echo fail)
This code takes %~1 value and I want to substitute %~1 with a path directly! Please help with the solution
For example:
a file named testfile.txt exists in folder C:\Files\
Logic should be something like below:
IF EXIST C:\Files\TESTFILE.txt (
echo file of case exists
) else (
echo file of this case does not exist
)
Here is a corrected form of Gerhard's original answer using FINDSTR:
dir "C:\files" /b /a-d | findstr /x /c:"TESTFILE.txt" && echo Found || echo Not found
The /c:"string" option is needed to force a literal interpretation (not regex), and to allow spaces in the name. The /X option is needed to force an exact match. You don't want to mistakenly match "the_TESTFILE.txt".
The above is probably the most straight-forward technique.
This can also be solved with a FOR statement. If %%F contains the name of an existing file (case insensitive), then %%~nxF will expand to the actual case sensitive name on disk.
But if %%F does not exists, then %%~nxF will never change the case. So IF EXIST must also be used.
The command must be carefully constructed to give the correct result. My goal is to have a self contained construct that allows use of && and || at the end to conditionally take action depending on whether the file exists or not.
pushd C:\files
(
for %%F in ("TESTFILE.txt") do (
if exist %%F if %%~F==%%~nxF popd & (call)
) && popd
) && echo NOT FOUND || echo FOUND
or on a single line
pushd C:\files&(for %%F in ("TESTFILE.txt") do (if exist %%F if %%~F==%%~nxF popd&(call))&&popd) && echo NOT FOUND || echo FOUND
Note the inverse logic. If the file exists with matching case, then (call) is the last executed command within the parentheses, resulting in a non-zero return code. If the file does not exists or does not match case, then popd is the last executed command within parentheses, resulting in a zero return code.
To search for the file with the prefered case:
#echo off
set "res=" && for /f "delims=" %%i in ('dir "C:\Files" /b /a-d') do if "%%i"=="TESTFILE.txt" set "res=%%i"
if defined res (echo %res% Found) else (echo File not found)
still using for /f but without setting a variable:
#echo off
for /f "delims=" %%i in ('dir "C:\files" /b /a-d') do if "%%i"=="TESTFILE.txt" echo File found & goto :eof
echo File not found
or simply without /f but you would need to
#echo off
for %%i in (C:\Files\*) do if "%%i"=="TESTFILE.txt" echo File found & goto :eof
echo File not found
Related
hope you can help me with this, i can't make it work what i need
I need to copy all the .pdf files from a source folder, create a folder with part of the name "T-123456" and add the respective PDF files found in the correct folder in the destination folder, but sometimes the name it varies or the reference change "SM17-123".
Example of files
HC002T-1234562436787004332
MV002T-1234562436787004332
PP _002_T-123456_24_3678_7004332
Types of direfents files
HC123CLG-32-172436787004259
HC123SM17-1802436787004044
i have this code created but it makes part of the job because the name varies and create folders incorrect for that files, sometimes the files have more digits in the beggining example 001 or 0001, so i dont know how to omit the other references files and only work whith files "T-123456" also i need the batch continuously working for new files created in the source folder and if i have another routhe where i have other types of file and copy to the correct reference it would be great.
#echo off
title Electronic File
:loop
cls
timeout -t 1 >nul
color b
for %%A in (*.pdf) do (
echo File Found %%A
for /f "delims=" %%B in ("%%A") do set fname=%%~nB
for /f "delims=" %%C in ("%%A") do set fextn=%%~xC
for /f "tokens=1* delims=" %%D in ("!fname:~5,8!") do set folname=%%D
echo Name folder !folname!
if not exist "!folname!" (
echo Folder !folname! dont exist, creating
md "!folname!" 2>nul
) else (
echo Folder !folname! exists
)
echo Copying file %%A to folder !folname!
xcopy "%%A" "!folname!"
)
echo on
md "C:\test %All%"
xcopy /s /y "X:\test\pdf" "W:\Electronic File %All%"
goto :loop
pause
for %%A in (*.pdf) do (
echo File Found %%A
set fname=%%~nA
set fextn=%%~xA
set folname=!fname:~5,8!
ECHO !folname!|FINDSTR /i /r "[A-Z]-[0-9][0-9][0-9][0-9][0-9][0-9]" >NUL
IF ERRORLEVEL 1 (
ECHO %%A - !folname! excluded
) ELSE (
echo Name folder !folname!
if not exist "!folname!" (
echo Folder !folname! dont exist, creating
ECHO md "!folname!" 2>nul
) else (
echo Folder !folname! exists
)
echo Copying file %%A to folder !folname!
ECHO xcopy "%%A" "!folname!"
)
)
Here's the meat of the matter. delayedexpansion needs to be on - you don't show that in your original code.
Note that there is no requirement for %%B, %%C, %%D as within the loop, %%A contains the filename and hence you can set the variables from that name.
Note that fextn will apparently always be .pdf since that is the extension you specify in your filemask *.pdf so setting it seems superfluous.
The syntax SET "var=value" (where value may be empty) may be used to ensure that any stray trailing spaces are NOT included in the value assigned.
The change I've introduced is to echo the directoryname to findstr, searching /i case-insensitively for /r a regular-expression which is one letter, a dash and then 6 numerics. If the directoryname matches then errorlevel will be set to 0 by findstr, otherwise, it will be set to 1.
The if errorlevel 1 means "if errorlevel is 1 or greater" and if that is so, the match was UNsuccessful, so report the filename and extracted directoryname; otherwise, go through your logic (I've changed it to simply echo the md and xcopy commands, for testing).
Given that we now have a variable structure,
for %%A in (*.pdf) do (
echo File Found %%A
set "copied="
set fname=%%~nA
set fextn=%%~xA
set folname=!fname:~5,8!
ECHO !folname!|FINDSTR /i /r "[A-Z]-[0-9][0-9][0-9][0-9][0-9][0-9]" >NUL
IF not ERRORLEVEL 1 call :process "%%A"
rem repeat this section for each match required - begin
if not defined copied (
set folname=!fname:~5,9!
ECHO !folname!|FINDSTR /i /r "[A-Z][A-Z][A-Z]-[0-9][0-9]-[0-9][0-9]" >NUL
IF not ERRORLEVEL 1 call :process "%%A"
)
rem repeat this section for each match required - end
if not defined copied ECHO %%A - !folname! excluded
)
goto :eof
:process
echo Name folder %folname%
if not exist "%folname%" (
echo Folder %folname% dont exist, creating
ECHO md "%folname%" 2>nul
) else (
echo Folder %folname% exists
)
echo Copying file %~1 to folder %folname%
ECHO xcopy "%~1" "%folname%"
set "copied=Y"
goto :eof
In your extended examples, it's not clear where the PP fits into the scheme.
The formula is reasonably simple. The start position is the first argument in the set (counting from first character=0) and the second the length to select. The regex match may be either a single character (matched literally) or [rangestart-rangeend] . matches any one character, so the first block I've shown selects from HC123CLG-32-172436787004259 from the 5th character (starting at 0) for 9 characters =CLG-32-17 and matches this against alpha,alpha,alpha,-,numeric,numeric,-,numeric,numeric.
On a match, errorlevel is set to 0, so the :process subroutine is called, with a parameter of %%A in quotes. The subroutine uses the value in folname and copies the file (name now in %1 - %~1 removes the quotes) as before.
So - it's as simple as repeating the block of code, altering the start and length of the string to be selected and changing the regex to suit the required pattern.
There are two areas where I need some guidance and not sure if this is possible or not. Please note that below code is working as intended.
#echo off
setlocal
set "sourcedir=C:\FILETEST"
pushd %sourcedir%
for /f "tokens=1,2*delims=-" %%a in (
'dir /b /a-d *-*--*.*'
) do if "%%c" neq "" (
md "%%a-%%b"
move "%%a-%%b--%%c" ".\%%a-%%b\"
)
popd
goto :eof
The above code caters for file names have a "-" and "--", for example filename "UK-London--filename.doc" would create a folder "UK-London" and put the file there.
However, there are also other filenames that are more detailed, for example filename "EU-UK--London-Camden--filename.doc". The below script works for this example and will create a folder for "EU-UK", then a subfolder "London-Camden" and put the file there:
#echo off
setlocal
set "sourcedir=c:\FILETEST"
pushd %sourcedir%
for /f "tokens=1,2,3,4*delims=-" %%a in (
'dir /b /a-d *-*--*-*--*.*'
) do if "%%e" neq "" (
md "%%a-%%b"
md "%%a-%%b/%%c-%%d"
move "%%a-%%b--%%c-%%d--%%e" ".\%%a-%%b\%%c-%%d\"
)
popd
goto :eof
The first issue that I am having is that I need to use both scripts to go through all files and it sometimes is a hit and miss. Is there a way to combine the two scripts with an "if exist" statement?
The second issue and more of a question is currently the delims is set to "-", can I add another delims e.g. "_"?
Thank you and please let me know if any questions.
Panos
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*.doc" '
) DO (
SET "filename=%%~na"
FOR /f "tokens=1-3delims=:" %%m IN ("!filename:--=:!") DO (
IF "%%o"=="" (
MD "%destdir%\%%m" 2>NUL
ECHO move "%sourcedir%\%%a" "%destdir%\%%m\"
) ELSE (
MD "%destdir%\%%m\%%n" 2>NUL
ECHO move "%sourcedir%\%%a" "%destdir%\%%m\%%n\"
)
)
)
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
I'm assuming all of your .doc files fit the masks provided.
The dir command produces a list of all of the .doc files (obviously, provide a different mask if required). Each name is then assigned to %%a and the name part only to filename.
Using delayedexpansion, convert each -- to : (a character that can't exist in a filename) and use the delims=: to tokenise to %%m..%%o. Then check whether the third token (and hence second level) exists and perform the appropriate create and move.
Note that md one\two will create one if it doesn't already exist. The 2>nul suppresses complaints that the directory already exists.
The required MOVE commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MOVE to MOVE to actually move the files. Append >nul to suppress report messages (eg. 1 file moved)
As for the delims issue, any character between the = and " is defined as a delimiter; all ranking equally. The line will be interpreted as delims token1 delims token2 ... where the delims string is a sequence of (any of (any of the delimiters))
I'm thinking you could use a more general approach: whatever the filename happens to be, change all occurrences of "--" to "\" so that you create a pathname (full file spec such as C:\path\to\name.ext). Then extract the parent directory from the pathname, and move the file accordingly.
Something like this (not tested):
setlocal enabledelayedexpansion
for %%a in (*) do (
set "pathname=%%a"
set "pathname=!pathname:--=\!"
for %%b in ("!pathname!") do set "parent=%%~dpb"
md !parent!
move "%%a" "!pathname!"
)
I am trying to write a batch file that can be used for the following task - search for certain text files and adding a text line in them - below the specified line. I am trying to use the following approach:
dir /s /a /b "%SystemDrive%\config*.ini" >> %userprofile%\temp.txt
for /F "tokens=* delims=," %%G IN (%userprofile%\temp.txt) DO (echo "%%G" >> %userprofile%\temp2.txt)
for /F "tokens=* delims=," %%G IN (%userprofile%\temp2.txt) DO (
SETLOCAL ENABLEDELAYEDEXPANSION
cd %%~dG%%~pG
set inputFile=%%~nG%%~xG
set outputFile=in.tmp
set _strInsert=TCPPortNumber=870
set _strFind=Random=No
FOR /F "usebackq delims=" %%A IN ("%inputFile%") DO (
Echo %%A | Find "%_strFind%" && ECHO %%A>>"%outputFile%" && ECHO %_strInsert%>>"%outputFile%"
IF [!errorlevel!] == [1] ECHO %%A>>"%outputFile%"
)
MOVE /Y "%outputFile%" "%inputFile%" && DEL /F /Q "%outputFile%"
Searching for config*.ini file(s) and writing results into temp.txt. Inserting quotes in case there are spaces in file paths for each line in temp.txt -> temp2.txt. Then for each file path in temp2.txt trying to insert TCPPortNumber=870 below the line Random=No. If I use a "hard" file path this approach works, but with reading the files path from temp2.txt it gives me an error: The system cannot find the file specified.
Can anyone help?
SETLOCAL ENABLEDELAYEDEXPANSION
dir /s /a /b "%SystemDrive%\config*.ini" >> %userprofile%\temp.txt
set outputFile=in.tmp
set _strInsert=TCPPortNumber=870
set _strFind=Random=No
for /F "usebackqdelims=" %%G IN ("%userprofile%\temp.txt") DO (
pushd %%~dpG
FOR /F "usebackq delims=" %%A IN ("%%~nxG") DO (
ECHO %%A>>"%outputFile%"
Echo %%A | Find "%_strFind%" && >>"%outputFile%" ECHO %_strInsert%
)
MOVE /Y "%outputFile%" "%%~nxG"
popd
)
endlocal
The setlocal command should not be within the loop (unless it is matched by an endlocal) because it is not a switch, but establishes a frame, hence within the loop, cmd is establishing many nested local environments.
The three constant strings also should appear outside of the loop since their values do not change.
The second tempfile is not required as it is simply the first with each line quoted.
Since %temp% may contain spaces, the for/f ... %%Gneeds to have the filename quoted, and consequently theusebackqoption. The line is to be accepted into%%Gin its entirity, sodelims=` is required, turning delimiters off.
The substring selectors may be combined, so ~dp delivers the drive and path and ~nx the name and extension.
In the original code, inputfile was being set up, but %inputfile% would be resolved to the value of inputfile at the time the entire block (parenthesised sequence of lines) was parsed not at run-time as the values change through execution of the code. This is the commonly-encountered delayed expansion problem - hundreds of references here on SO.
Since what appears to be needed is to insert a line after a particular line, we can simply reproduce each line then see whether the insertion is required, which simplifies the code. The placement of the redirector to before the echo overcomes the Windows-NT characteristic of selecting the device to be redirected by preceding the redirector with a device number.
Finally, move /y forces the replacement of the input file with the output file, so the output file will no longer exist
I haven't actually tried this code - you should execute it against a small copied subtree of the real data and evaluate it before relying on it.
small fix - changed original cd to pushd and added corresponding popd also removed superfluous %
PUSHD changes the current directory to that specified. POPD restores the original current-directory.
The extra % was a keying error (my normal machine is ill and I have to use the laptop - and boy, do I loathe the keyboard...)
I have some 500 .txt files in a folder. Of them, some 100 files contain a text that I wish to change. I have used the below code to do that.
used Repl.bat and the below code:
for %%F in (*.txt) do (
type "%%F"|repl Apples Mangoes >"%%F.new"
move /y "%%F.new" "%%F"
)
Since this searches through all the files, the files are getting modified. I am unable to know in which files, the text has been replaced.
My actual task is to change the string and get the modified files into another folder.
I tried using the below code to move the modified files. but since all the files are getting modified, I am clueless as what to do.
ECHO OFF
set source=C:\abc\
set destination=C:xyz\
for /F "tokens=2-4 delims=/ " %%i in ('date /t') do set yyyymmdd1=%%j"."%%i"."%%k
if exist %destination% goto GO
:GO
mkdir %destination%%yyyymmdd1%
xcopy %source%* %destination% /m/s/d/y/c/v/r
echo.
echo Finished copying %source% to %destination%
echo.
echo Created %destination%%yyyymmdd1%
pause
Thanks in advance
To simply find out what files actually have been modifed, with respect to their contents only, you can use the following code snippet, which collects all the modified files in the log file change.log:
#echo off
> "change.log" (
for %%F in ("*.txt") do (
type "%%~F" | > "%%F.new" repl Apples Mangoes
> nul fc /L "%%~F" "%%~F.new" || echo "%%~F"
> nul move /Y "%%~F.new" "%%~F"
)
)
This uses the fc command and the fact that it sets the ErrorLevel to 0 for matching files, and to 1 otherwise. || constitutes a conditional command separator which executes the next command only in case of a non-zero ErrorLevel (also known as exit code or return code).
The comparison is done in text mode. To change it to binary mode, replace fc /L by fc /B.
The redirection > nul avoids any messages of fc (like Comparing files [...], FC: no differences encountered) or move (like 1 file(s) moved.). If you want to see sch messages on screen, replace the > nul by > con.
To move the collected modified files afterwards, use the following command line in a batch script:
for /F "delims=" %%I in ("change.log") do (move "%%~I" "\path\to\destination\")
I've been trying to get the syntax right, but I'm having issues. Not only am I not getting the syntax right, but I would like this script to:
Locate all files of a certain criteria on All Drives in a network
check to see if the file is the updated file (or new file)
if it is NOT the new or updated file, locate the new file and replace it
ALSO! If I can get this to work on a schedule, such as every 6 hours... that would be a real help
I got this code to work once, but I changed it a couple times and saved over it.
#echo off
SETLOCAL
cls
:locate_old
for /d /r Z:\ %%a in (*) do if exist "%%~fa\old.file" set "oldFile=%%~fa\old.file"
if not defined oldFile (
echo old file not found...
) else (
echo old file found&GOTO oldFileCheck
)
:oldFileCheck
find "old file text" "%oldFile%" && echo old file is already updated || GOTO findNewFile
:findNewFile
for /d /r Z:\ %%a in (*) do if exist "%%~fa\new.file" set "newFile=%%~fa\new.file"
if not defined newFile (
echo no new file detected...
) else (
echo new file located...&GOTO fileSwap
)
:fileSwap
copy /y "%newFile%" "%oldFile%" && echo file updated || file not updated
If I understand your requirement, you want to replace all "old.file" files on Z:\ with "new.file" files if they aren't updated already. This is untested:
#if not defined debug_batch_files echo off
REM You can set debug_batch_files to 1 and quickly see verbose execution
pushd Z:\
for /f "delims=" %%a in ('dir /b /s /a-d new.file') do echo xcopy /D /Y "%%~fa" "%%~dpaold.file"
REM Remove "echo" from the above line if it displays the right paths.
popd