i just subscribe here.
I would want to hide the "Acces is denied." error message in case writing to a read-only file fails. Could someone tell me why the following code doesn't work as expected ? I'm using Windows 10.
:: This file is assumed to be read-only.
echo( >"MyReadOnlyFile.txt" 2>nul
( echo( ) >"MyReadOnlyFile.txt" 2>nul
In both case the "Access is denied." message is displayed, although the following "How-to: Redirection" page at SS64 says the contrary: https://ss64.com/nt/syntax-redirection.html
Redirect to NUL (hide errors)
command >filename 2> nul Redirect output to file but suppress error
(command)>filename 2> nul Redirect output to file but suppress CMD.exe errors
Thanks in advance for your help.
Lionel.
CodePudding user response:
As stated already in the comments, the Access is denied message is output to stdOut, as opposed to the expected stdErr.
Since your task is related to a read only issue, (there are other reasons why that message may be output), I'd offer this relatively simple alternative:
@Dir "MyReadOnlyFile.txt" /A:-DR /B 1>NUL 2>&1 || (Echo() 1>>"MyReadOnlyFile.txt"
It simply determines if the existing file is read only, and only performs a write operation if it is not.
Alternatively you could use the same method to reset the read only attribute, write to the file, then apply the read only attribute again:
@Set "File=MyReadOnlyFile.txt"
@Dir "%File%" /A:-DR /B 1>NUL 2>&1 && (
%SystemRoot%\System32\attrib.exe -R "%File%" 2>NUL
If Not ErrorLevel 1 (
(Echo() 1>>"%File%"
%SystemRoot%\System32\attrib.exe R "%File%"
)
) || (Echo() 1>>"%File%"
CodePudding user response:
Thanks for your quick answers, i really appreciate.
Microsoft has been telling us for over a decade that PowerShell is the future of scripting.
I know indeed. I'm currently optimizing my own application in Batch third party tools (a retrogame launcher, the main Batch script is about 41000 lines) by improving various stuffs here and there, so i guess Powershell will wait for a next project (smile). But anyway thanks for your advice, you're right.
Alternatively you could use the same method to reset the read only attribute, write to the file, then apply the read only attribute again:
This dir /A:-DR /B is nice and fast way to test if a file is read-only, indeed. There may be benefits to proceed in this way instead of 1. grabbing the file attribute with a more conventional for %%F in ("MyReadOnlyFile.txt") do set "file.attr=%%~aF" then 2. testing the second character by enabling delayed expansion. I will check where i can use it in my code to optimize some parts slightly, thank you for your suggestion Compo.
The error isn't written to STDERR, but to STDOUT (don't ask me, why), so echo( >"MyReadOnlyFile.txt" 1>nul suppresses the error message (sadly along with any possible useful output)
Thanks for your answer Stephan. Well, we know that Batch is quite insane often, but a such behavior would be more than insanity (smile). Redirecting stdout 1>nul doesn't hide the error message (as expected). However, surrounding the command and file redirection with brackets works as expected:
(echo( >"MyReadOnlyFile.txt") 2>nul
It might be a possible typing error on SS64 about the position of surrounding brackets, it should be (command >"filename") 2>nul. The error message is redidrected to stderr as expected, confirmed by the following if you open the "stderr.txt" file.
(echo( >"MyReadOnlyFile.txt") 2>"stderr.txt"
Again thank you to have replied, i did read a ton of threads on stackoverflow during the whole development of my application but i never subscribed. So that's a special feeling to have opened an account finally.
EDIT I also add these two in case it can help someone.
rem Merge stderr to stdout.
set "_mute=>nul 2>&1" & set "_mute1=1>nul" & set "_mute2=2>nul"
rem Force ERRORLEVEL to 0.
set "_errlev0=(call )"
rem If you're lazy to type it each time (i am !).
set "_ede=enabledelayedexpansion"
rem Existing file name.
set "file.path=MyTestFile.txt"
rem Paths to the SQLite executable and SQLite database (example).
set "sqlite_file.path=C:\SQLite\SQLite.exe"
set "db_file.path=C:\Database\MyBase.db"
setlocal %_ede%
rem --- Test1 ---
%_errlev0%
echo ERRORLEVEL=!ERRORLEVEL!
(echo| set /p dummy_name="Hello & world">>"!file.path!") %_mute% && (
echo Test1 succeeded
) || (
echo Test1 failed
)
echo %ERRORLEVEL=!ERRORLEVEL!
rem --- Test2 ---
:: Whatever SQLite query of your choice.
set "sql_query=SELECT arcade_t.description FROM arcade_t WHERE arcade_t.description LIKE '% 