Windows 批处理脚本:如何递归遍历除某些文件类型和文件夹之外的所有文件?

Windows 批处理脚本:如何递归遍历除某些文件类型和文件夹之外的所有文件?

我正在尝试对除 .git 文件夹中的文件之外的所有文件执行替换字符串操作,并且所有pycache可以嵌套在任何嵌套目录中的目录。我正在包含 .git 文件夹的根目录中执行脚本。

for /r /d %%F in (*) do (
    echo Checking: %%F
    if not "%%~xF"==".sh" if not "%%~xF"==".png" if not "%%~xF"==".bat" if not "%%~dpF"=="__pycache__\" if not "%%~dpF"==".git\" (
        echo Found file: %%F
        findstr /C:"{{ADDON_NAME_PACKAGE}} {{ADDON_NAME}} {{ADDON_NAME_FULL}}" "%%F" >nul 2>&1
        if not errorlevel 1 (
            echo %%F
            set "file=%%F"
            setlocal DisableDelayedExpansion
            set "cmd=sed -i -e ""s/%replace_package%/%package_name%/g"" -e ""s/%replace_addon_name%/%addon_short_name%/g"" -e ""s/%replace_addon_name_full%/%addon_full_name%/g"" ""!file!""
            endlocal & !cmd!
            echo Replaced placeholders in !file!
        )
    )
)

但我被困在如果此循环的条件是,即使使用排除,仍会打印出 .git 文件夹中的所有文件if not "%%~dpF"==".git\"。为什么?我找不到任何解决方案,甚至聊天 gpt 也无法告诉我。人工智能怎么可能不知道这一点?也if not "%%~dpF"=="%CD%\.git\"不起作用。

for /r /d %%F in (*) do (
    echo Checking: %%F
    if not "%%~xF"==".sh" if not "%%~xF"==".png" if not "%%~xF"==".bat" if not "%%~dpF"=="__pycache__\" if not "%%~dpF"==".git\" (
        echo Found file: %%F

它仍然会打印出 .git 文件夹和 __pycache__ 文件夹中的文件。使用 Unix/Linux 很容易实现这一点

replace_package="{{ADDON_NAME_PACKAGE}}"
replace_addon_name="{{ADDON_NAME}}"
replace_addon_name_full="{{ADDON_NAME_FULL}}"

perform_replacements() {
    local file="$1"
    local package_name="$2"
    local addon_short_name="$3"
    local addon_full_name="$4"

    sed -i "s/${replace_package}/${package_name}/g; s/${replace_addon_name}/${addon_short_name}/g; s/${replace_addon_name_full}/${addon_full_name}/g" "$file"
}

find . \( -name .git -o -name __pycache__ \) -prune -o \( -type f -not -name "*.sh" -not -name "*.png" \) -print0 | while IFS= read -r -d '' file; do
    perform_replacements "$file" "$package_name" "$addon_short_name" "$addon_full_name"
    echo "Replaced placeholders in $file"
done

所以我不明白为什么在 Windows .bat 文件中执行相同操作会如此复杂?这是怎么回事?

答案1

这不是完整的答案。 仅是一个使用 PowerShell 的示例。

将其保存为扩展名为 . 的文件.ps1(例如:)test.ps1,并将其放在工作目录中。要执行,Right Click> Run with PowerShell.

  • 官方格式
$WL1 = @('.bat', '.png', '.sh', '.ps1')
$WL2 = @('.git', '__pycache__')
if ($PWD.Path -ne $PSScriptRoot) {Push-Location -Path $PSScriptRoot}
Get-ChildItem -Recurse | Where {$_.Name -notin $WL2 -and $_.Extension -notin $WL1} |
ForEach-Object {$_.Name}
pause 

这将显示除过滤器之外的所有文件和目录$WL1 $WL2

$WL1您可以在 中按扩展名添加要排除的文件或文件夹,并在 中按名称添加要排除的文件或文件夹$WL2

  • 短格式
$WL1='.bat','.png','.sh','.ps1'
$WL2='.git','__pycache__'
Pushd $PSScriptRoot
GCI -R|? Name -notin $WL2|? Extension -notin $WL1|% Name
pause 

要检查所有可用的过滤器,您可以在目录中的 PowerShell 控制台中键入Get-ChildItem -Recurse | Get-Member或。GCI -R|GM

答案2

尽管 PowerShell 脚本比普通批处理脚本更容易编写和阅读,但它们缺少一件事:普通用户很难执行它们,因为您不能双击它们。

不过,也有简单的解决方案,其中最常见的两个是:

简单一点

像平常一样编写 PowerShell 脚本。然后创建一个 cmd 脚本,在其中输入powershell.exe -ExecutionPolicy Bypass -NoProfile -NoLogo -File "%~dp0\MyPowerShellFile.ps1。现在,您可以将这两个文件提供给用户,他们只需像往常一样双击 bat 文件,它就会执行 powershell 脚本。

这样,用户(和您自己)就可以更轻松地使用批处理文件,同时获得 PowerShell 的所有功能。缺点是您现在有两个文件,这将导致:

仅限一个文件

与前一个类似,但不是调用单独的文件,您还可以将整个脚本集成到批处理文件中,从而避免需要两个文件。

您可以使用-EncodedCommand参数将包含整个脚本的 base64 编码字符串传递给 PowerShell 来执行此操作。

一个简单的 PowerShell 函数(在 cmd 中编写等效代码很有趣..)可以接受任何 PS1 文件并创建一个 bat 文件,如下所示:

function Convert-PowerShellToBatch
{
    param
    (        
       [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [string]
        [Alias("FullName")]
        $Path
    )
 
    process
    {
        $encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path $Path -Raw -Encoding UTF8)))
        $newPath = [Io.Path]::ChangeExtension($Path, ".bat")
        "@echo off`npowershell.exe -NoExit -encodedCommand $encoded" | Set-Content -Path $newPath -Encoding Ascii
    }
}

来源因为我手头没有脚本集合-但看起来正确。

相关内容