windows 最好的方法来检查目录是否是可写的BAT脚本?

mlmc2os5  于 2023-03-24  发布在  Windows
关注(0)|答案(6)|浏览(209)

如何从批处理脚本检查目录是否可由执行用户写入?
以下是我目前所做的尝试:

> cd "%PROGRAMFILES%"

> echo. > foo
Access is denied.
> echo %ERRORLEVEL%
0

好吧,那么...

> copy NUL > foo
Access is denied.
> echo %ERRORLEVEL%
0

也不是?那...

> copy foo bar
Access is denied.
        0 file(s) copied.
> echo %ERRORLEVEL%
1

这可以工作,但如果文件不存在,它就会中断。
我读过一些关于内部命令不设置ERRORLEVEL的文章,但是copy显然在最后一种情况下这样做了。

fae0ux8s

fae0ux8s1#

最简单的方法就是对它运行一个命令来确定它是否被拒绝。你也可以使用CACLS来确定权限是什么或不是什么。下面是一个例子。
在CMD类型CACLS /?
CACLS "filename"会给予你当前文件允许的权限。R =读,W =写,C =更改(和写一样?),F =完全访问。
编辑:您也可以使用目录名称。
所以要做一个检查,你会:

FOR /F "USEBACKQ tokens=2 delims=:" %%F IN (`CACLS "filename" ^| FIND "%username%"`) DO (
 IF "%%F"=="W" (SET value=true && GOTO:NEXT)
 IF "%%F"=="F" (SET value=true && GOTO:NEXT)
 IF "%%F"=="C" (SET value=true && GOTO:NEXT)
 SET value=false
)
ECHO This user does not have permissions to write to file.
GOTO:EOF
:NEXT
ECHO This user is able to write to file.
mzillmmw

mzillmmw2#

您可以编写copy %0 foo来复制批处理文件本身。
这将永远存在。
请记住在之后删除该文件,并确保您没有用该名称覆盖现有文件。
应该有更好的方法来做这件事,但我不知道任何。

EDIT:最好试试mkdir foo

如果批处理文件是在网络上运行的(或者如果它非常大),这可能会更快。

5anewei6

5anewei63#

set testdir=%programfiles%
set myguid={A4E30755-FE04-4ab7-BD7F-E006E37B7BF7}.tmp
set waccess=0
echo.> "%testdir%\%myguid%"&&(set waccess=1&del "%testdir%\%myguid%")
echo write access=%waccess%
hgc7kmma

hgc7kmma4#

我发现在批处理文件中执行copy会向STDERR返回一个错误,但%ERRORLEVEL%没有被修改(仍然是0)。因此解决方法是将该命令与set的条件执行结合起来。

copy /Y NUL "%FOLDER%\.writable" > NUL 2>&1 && set WRITEOK=1
IF DEFINED WRITEOK ( 
  rem ---- we have write access ----
  ...
 ) else (
  rem ---- we don't ----
  ...
)

这是在XP和7上测试的,似乎工作可靠。

yhuiod9q

yhuiod9q5#

Mechaflash的答案的扩展,并通过为“测试”文件生成唯一的文件名来解决覆盖文件的问题。

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "a=%~1"
SET "b="
SET "g=0"
:a
SET "c= `1234567890-=qwertyuiop[]asdfghjkl;'zxcvbnm,.~!@#$%%^&()_+QWERTYUIOP{}ASDFGHJKLZXCVBNM"
SET /A "d=0, e=1"
:b
IF "!c!" NEQ "" (
    IF "!c:~%d%,1!" NEQ "" (
        IF EXIST "!a!\!b!!c:~%d%,1!" (
            SET "c=!c:~0,%d%!!c:~%e%!"
        ) ELSE (
            SET /A "d=!d!+1, e=!e!+1"
        )
        GOTO :b
    )
)
IF "!c!" EQU "" (
    SET "c= `1234567890-=qwertyuiop[]asdfghjkl;'zxcvbnm,.~!@#$%%^&()_+QWERTYUIOP{}ASDFGHJKLZXCVBNM"
    :c
    IF "!c!" NEQ "" (
        IF "!c:~%d%,1!" NEQ "" (
            SET /A "d=!d!+1"
            GOTO :c
        )
    )
    SET /A "d=!d!-1"
    SET /A "f=%RANDOM%*!d!/32768"
    SET "b=!b!!c:~%f%,1!"
    GOTO :a
) ELSE (
    SET /A "d=!d!-1"
    SET /A "f=%RANDOM%*!d!/32768"
    SET "b=!b!!c:~%f%,1!"
)
((ECHO EXIT>"!a!\!b!" && SET "g=1") & IF EXIST "!a!\!b!" DEL /F "!a!\!b!") >NUL 2>&1
ENDLOCAL & (SET "a=%g%")
IF "%a%" EQU "1" ECHO TRUE

%~1是输入目录)
编辑:如果你想要一个更安全的选择

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "a=%~1"
SET "b="
SET "g=0"
:a
SET "c= `1234567890-=qwertyuiop[]asdfghjkl;'zxcvbnm,.~!@#$%%^&()_+QWERTYUIOP{}ASDFGHJKLZXCVBNM"
SET /A "d=0, e=1"
:b
IF "!c!" NEQ "" (
    IF "!c:~%d%,1!" NEQ "" (
        IF EXIST "!a!\!b!!c:~%d%,1!" (
            SET "c=!c:~0,%d%!!c:~%e%!"
        ) ELSE (
            SET /A "d=!d!+1, e=!e!+1"
        )
        GOTO :b
    )
)
IF "!c!" EQU "" (
    SET "c= `1234567890-=qwertyuiop[]asdfghjkl;'zxcvbnm,.~!@#$%%^&()_+QWERTYUIOP{}ASDFGHJKLZXCVBNM"
    :c
    IF "!c!" NEQ "" (
        IF "!c:~%d%,1!" NEQ "" (
            SET /A "d=!d!+1"
            GOTO :c
        )
    )
    SET /A "d=!d!-1"
    SET /A "f=%RANDOM%*!d!/32768"
    SET "b=!b!!c:~%f%,1!"
    GOTO :a
) ELSE (
    SET /A "d=!d!-1"
    SET /A "f=%RANDOM%*!d!/32768"
    SET "b=!b!!c:~%f%,1!"
)
IF EXIST "!a!\!b!" (
    SET "b=!b:~0,-1!"
    GOTO :a
) ELSE (
    ((ECHO EXIT>"!a!\!b!" && SET "g=1") & IF EXIST "!a!\!b!" DEL /F "!a!\!b!") >NUL 2>&1
)
ENDLOCAL & (SET "a=%g%")
IF "%a%" EQU "1" ECHO TRUE
j91ykkif

j91ykkif6#

您可以使用echo解决此问题。

(> %tmpfile% echo) 2>NUL && (del %tmpfile% && goto can-write || goto can-write-not-del) || goto cannot-write

尝试用echo写入文件。如果成功(&&),请再次删除%tmpfile%并执行一些操作。如果出错(||),请执行其他操作。

示例

C:\>check-directory.bat
usage: check-directory.bat <folder>

C:\>check-directory.bat is-writable
Can write to C:\is-writable

C:\>check-directory.bat is-not-writable
Can **not** write to C:\is-not-writable

check-directory.bat

@echo off

if "%~1" == "" (
    echo usage: %0 ^<folder^>
    goto :eof
)
if not exist "%~1\*" (
    echo The folder '%~1' does not exist.
    goto :eof
)

set tmpfile=%~1\.deleteme
(> %tmpfile% echo) 2>NUL && (del %tmpfile% && goto can-write || goto can-write-not-del) || goto cannot-write

:cannot-write
echo Can **not** write to %CD%
goto :eof

:can-write
echo Can write to %CD%
goto :eof

:can-write-not-del
echo Can write to %CD% but couldn't delete %tmpfile%.
goto :eof

相关问题