这是我的将数据添加到特定文件的脚本:
@echo off
FIND /C /I "foo" %WINDIR%\system32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 0 ECHO ^8.8.8.8 foo>>%WINDIR%\System32\drivers\etc\hosts
当文件末尾包含换行符时,它可以正常工作:
来自:
data
收件人:
data
8.8.8.8 foo
但是当文件末尾不包含新行时,我将获得连接的行:
来自:
data
收件人:
data8.8.8.8 foo
对于带有 AND 且结尾没有换行符的文件,我该怎么做才能使代码正常工作?
答案 0 :(得分:2)
对于此任务,我建议使用以下批处理文件代码:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "HostsFile=%SystemRoot%\System32\drivers\etc\hosts"
if not "%ProgramFiles(x86)%" == "" if exist %SystemRoot%\Sysnative\cmd.exe set "HostsFile=%SystemRoot%\Sysnative\drivers\etc\hosts"
if not exist %HostsFile% goto AppendData
%SystemRoot%\System32\findstr.exe /I /L /C:"foo" %HostsFile% >nul
if not errorlevel 1 goto EndBatch
%SystemRoot%\System32\findstr.exe /R /V "$" %HostsFile% >nul
if not errorlevel 1 echo/>>%HostsFile%
:AppendData
>>%HostsFile% echo 8.8.8.8 foo
:EndBatch
endlocal
第三行用标准文件路径定义环境变量HostsFile
,该变量正好在32位Windows由32位cmd.exe
执行的批处理文件或64位Windows由64位执行的批处理文件中目录cmd.exe
中的%SystemRoot%\System32
位。
第四行根据Windows File System Redirector考虑了WOW64 Implementation Details。如果定义了名称为ProgramFiles(x86)
且具有非空值的环境变量,则该批处理文件将在64位Windows上执行。但是,如果存在cmd.exe
,则批处理文件由目录%SystemRoot%\SysWOW64
中的32位%SystemRoot%\Sysnative\cmd.exe
执行。重定向器Sysnative
对于x64应用程序不存在。在这种情况下,必须在文件路径中使用hosts
重定向器,才能从64位Windows的32位环境中引用文件Sysnative
。
接下来检查文件hosts
是否存在。如果该文件不存在,则可以在不进行任何进一步检查的情况下将要追加的数据行直接写入该文件,从而可以在这种情况下创建文件hosts
。
否则,命令 FINDSTR 用于搜索不区分大小写的foo
字面意义的搜索字符串,并将可能找到的行重定向到设备 NUL 强>。如果存在至少一个正匹配项,则 FINDSTR 以值0
退出,如果在任何行上都找不到搜索字符串,则以值1
退出。
if not errorlevel 1
表示 IF 退出代码为 NOT GREATER或EQUAL 1 ,即低于1 ,或在这种情况下,由于 FINDSTR 而导致等于0 的情况下,几乎所有应用程序和命令都不会以负值退出。因此,如果此条件为真,则文件hosts
至少包含一次搜索到的字符串,并且文件上没有任何更改。
否则,再次使用 FINDSTR 来搜索带有正则表达式的行尾,并输出所有由于选项{{ 1}}。因此,如果文件/V
中的最后一行没有行尾,则 FINDSTR 以值hosts
退出,因为输出了一行无行尾,因此该输出重定向到设备< strong> NUL 。
如果由于文件0
而退出 FINDSTR 并返回值hosts
,则行结尾将附加到文件0
,而在附加下一个数据之前,行末没有结尾添加到此文件的行。
如果未在本地管理员提升权限的情况下执行批处理文件,或者文件hosts
设置了只读属性,或者受脚本保护,则该代码无法正常工作。
要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。
hosts
echo /?
endlocal /?
findstr /?
goto /?
if /?
set /?
另请参阅DosTips论坛主题:ECHO. FAILS to give text or blank line - Instead use ECHO/
答案 1 :(得分:2)
FINDSTR有一个奇怪的怪癖,如果输入流不以\r\n
(换行)结尾,它会将\n
(回车,换行)附加到管道输入。有关更多信息,请参见https://stackoverflow.com/a/8844873/1012053上的 管道和重定向输入可能附加了<CR><LF>
部分。
仅当需要时,您可以使用此技巧有选择地添加缺少的换行符。
@echo off
setlocal
set "file=%windir%\system32\drivers\etc\hosts"
findstr /m /i "foo" "%file%" >nul || (
(
type "%file%" | findstr "^"
echo 8.8.8.8 foo
) >"%file%.new"
move /y "%file%.new" "%file%"
)
我选择使用FINDSTR
而不是FIND
查找foo,并且在错误时使用||
有条件执行,而不是使用IF
语句来检查{{1 }}。
管道输入FINDSTR的限制:
如果您有我的JREPL utility,则可以使用一种“简单”的衬纸,该衬纸应始终有效(我使用了连续行以使其更易于阅读):
ERRORLEVEL
它只是读取每一行,并使用\ r \ n行终止符再次将其写出,然后findstr /m /i "foo" "%WINDIR%\system32\drivers\etc\hosts" >nul ||^
jrepl "^" "" /jend "output.WriteLine('8.8.8.8 foo')"^
/f "%WINDIR%\system32\drivers\etc\hosts" /o -
选项在末尾追加多余的行。
答案 2 :(得分:1)
一种更简单的方法是:
@echo off
find /C /I "foo" %windir%\system32\drivers\etc\hosts
if %errorlevel% NEQ 0 (echo. & echo 8.8.8.8 foo)>>%WINDIR%\System32\drivers\etc\hosts
这是单行代码,对您来说更简单。
答案 3 :(得分:0)
如果您不介意其他换行/空白行,则可以添加
ECHO. >>%WINDIR%\System32\drivers\etc\hosts
即
@echo off
FIND /C /I "foo" %WINDIR%\system32\drivers\etc\hosts
IF %ERRORLEVEL% NEQ 0 (
ECHO.>>%WINDIR%\System32\drivers\etc\hosts
ECHO 8.8.8.8 foo>>%WINDIR%\System32\drivers\etc\hosts
)