如何在批处理脚本中检查文件/目录是否可写

7
在Bash中,我会使用
[ -w ... ]

在 Windows 中,批处理文件的等效物是什么?

可能是Best way to check if directory is writable in BAT script?的重复问题。 - darthbith
@darthbith,如果这个问题比被认为是重复的问题早了一年以上,那它怎么可能是一个重复的问题呢? - Marc Mutz - mmutz
那么也许重复的内容应该走另一条路 ¯_(ツ)_/¯ 不过在我看来,那个回答更好。 - darthbith
6个回答

3
据我所知,你可以找出文件是否存在,但是除了尝试向其写入内容外,无法知道它是否可写。这不仅涉及到没有R标志;网络和NTFS权限也有关(可能还包括组策略)。
如果你能重新编写你的代码,那么你可以通过errorlevel捕获写操作的返回码。

+1 提及权限。这绝对不仅仅是只读标志的问题,可以使用%~ax或类似方法轻松检查此问题。 - Joey
这真是令人惊讶,一个被接受的stackoverflow答案在一段时间后变得不正确:https://dev59.com/Y0vSa4cB1Zd3GeqPbx4_#59884789 - Andry
@Andry,您能否详细说明此答案中哪些信息已过时?除非我漏看了什么,您分享的链接只显示如何尝试写入文件以确定是否成功。 - Álvaro González
@Álvaro González 如果访问时间不改变,它就不会尝试写入,因此有一种方法可以知道它是否可写,而无需实际尝试写入。 - Andry

1
抱歉打扰了大家。这可能不是您正在寻找的100%解决方案,但我已经在Apache Tomcat的使用日志文件中使用过它,效果非常完美。感谢@dbenham提供的精彩代码!https://dev59.com/SWkv5IYBdhLWcg3wjxdl#10520609
SETLOCAL ENABLEDELAYEDEXPANSION
REM TOMCAT LOGS
FOR /r "D:\logs" %%X IN (*) DO (
    SET FileName=%%~nxX
    2>nul (   >>D:\logs\!FileName!" (call )) && (
    REM DO STUFF HERE
    SET ModDt=%%~tX
    FOR /f "tokens=1-3 delims=.:/ " %%j IN ("!ModDt!") DO SET FDate=%%l-%%j-%%k&Set RegDate=%%j-%%k-%%l
    IF "%CurrentDate%" NEQ "!FDate!" (
        IF %%~zX GTR 0 (
            ECHO ARCHIVING "D:\logs\!FileName!" >> %logfile%
            7za.exe -tzip -y a "D:\Zips\%COMPUTERNAME%-Tomcat-!RegDate!-compressed.zip" "D:\logs\!FileName!" && (
            DEL /Q "D:\logs\!FileName!"
            ) || (
                if "%ERRORLEVEL%" == "2" (
                    echo Zipping failed ^(exit status %ERRORLEVEL%^).  Trying again in 5 seconds...
                ) else (
                    echo Zip completed with warnings ^(most likely because a file was locked by another
                    echo process and had to be skipped^).  Trying again in 5 seconds...
                )
                del "D:\Zips\%COMPUTERNAME%-Tomcat-!RegDate!-compressed.zip" >NUL 2>&1
                PING 0.0.0.0 -n 6 -w 1000 >NUL
            )
        )
    )
    REM END OF UNLOCKED ZONE
    ) || (
    ECHO FILE IS LOCKED
    )
)

1

这是旧的,但我在这里没有找到它:

lock.bat

(
  echo.123
  pause
) > "1.txt"

test.bat

move /Y "1.txt" "1.txt" >nul 2>nul
echo.%ERRORLEVEL%
move 命令不会更改文件的创建、修改和访问时间。

https://www.dostips.com/forum/viewtopic.php?t=5542


为了检查目录的访问权限,您可以使用相同的方法使用“rename”命令:
rename "path\1.txt" "1.txt" >nul 2>nul
echo.%ERRORLEVEL%

为了测试它,只需在路径\中添加deny all以针对Everyone


0

你可以使用VBScript这样做

Set objFS=CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments
strFile = objArgs(0)
Set objFile = objFS.GetFile(strFile)
If Not objFile.Attributes And 1 Then
   WScript.Echo "The file is Read/Write."
Else
   WScript.Echo "The file is Read-only."
End If

将其保存为check.vbs并在命令行上运行

c:\test> cscript //nologo check.vbs myfile

ACLs也涉及其中。请参考Álvaro的回答。 - Joey

0
我发现最可靠的方法是将NUL复制到目标目录中的一个文件。
如果目录不存在或目录不可写入当前用户,则此操作将以1退出。
我使用/B作为NUL是二进制文件,/Y用于覆盖现有文件。
copy /Y /B NUL "c:\test\test.txt"
echo %ERRORLEVEL%

-1
ls -l foo.txt

对于不可写的文件,输出-r--r--r-- 对于可写的文件,输出-rw-r--r--

您可以存储该值并检查第3个字符是" w "表示可写还是"-"表示不可写。

在条件语句中使用类似% myVar:~2,1%的某些语法。

不确定这对操作系统的依赖性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接