自动删除Subversion无版本文件

时间:2008-10-27 08:39:35

标签: svn build-automation

是否有人知道以递归方式删除工作副本中不受版本控制的所有文件的方法? (我需要这样才能在我的自动构建VMware中获得更可靠的结果。)

32 个答案:

答案 0 :(得分:138)

这适用于bash:

 svn status | egrep '^\?' | cut -c8- | xargs rm

Seth Reno更好:

svn status | grep ^\? | cut -c9- | xargs -d \\n rm -r 

它处理文件名中的无版本文件夹和空格

根据下面的评论,这仅适用于subversion不知道的文件(status =?)。 subversion 知道的任何内容(包括忽略的文件/文件夹)都不会被删除。

如果您使用的是subversion 1.9或更高版本,则只需使用svn cleanup命令和--remove-unversioned和--remove-ignored选项

答案 1 :(得分:71)

我试图做同样的事情时跑过这个页面,但不是为了自动构建。

在看了一下之后,我在TortoiseSVN中发现了'扩展上下文菜单'。按住shift键并右键单击工作副本。 TortoiseSVN菜单下现在还有其他选项,包括“删除未版本化的项目...... ”。

虽然可能不适用于这个特定问题(即在自动构建的环境中),但我认为对于其他希望做同样事情的人来说可能会有所帮助。

答案 2 :(得分:22)

编辑:

Subversion 1.9.0引入了一个选项来执行此操作:

svn cleanup --remove-unversioned

在此之前,我使用这个python脚本来做到这一点:

import os
import re

def removeall(path):
    if not os.path.isdir(path):
        os.remove(path)
        return
    files=os.listdir(path)
    for x in files:
        fullpath=os.path.join(path, x)
        if os.path.isfile(fullpath):
            os.remove(fullpath)
        elif os.path.isdir(fullpath):
            removeall(fullpath)
    os.rmdir(path)

unversionedRex = re.compile('^ ?[\?ID] *[1-9 ]*[a-zA-Z]* +(.*)')
for l in  os.popen('svn status --no-ignore -v').readlines():
    match = unversionedRex.match(l)
    if match: removeall(match.group(1))

这似乎做得很好。

答案 3 :(得分:19)

请参阅:svn-clean

答案 4 :(得分:9)

如果您使用的是Windows命令行,

for /f "tokens=2*" %i in ('svn status ^| find "?"') do del %i

改进版本:

for /f "usebackq tokens=2*" %i in (`svn status ^| findstr /r "^\?"`) do svn delete --force "%i %j"

如果您在批处理文件中使用它,则需要将%

加倍
for /f "usebackq tokens=2*" %%i in (`svn status ^| findstr /r "^\?"`) do svn delete --force "%%i %%j"

答案 5 :(得分:7)

我将此添加到我的windows powershell配置文件

function svnclean {
    svn status | foreach { if($_.StartsWith("?")) { Remove-Item $_.substring(8) -Verbose } }
}

答案 6 :(得分:5)

Linux命令行:

svn status --no-ignore | egrep '^[?I]' | cut -c9- | xargs -d \\n rm -r

或者,如果您的某些文件归root所有:

svn status --no-ignore | egrep '^[?I]' | cut -c9- | sudo xargs -d \\n rm -r

这是基于Ken的回答。 (肯的答案会跳过忽略的文件;我的答案会删除它们。)

答案 7 :(得分:4)

您是否可以直接导出到新位置并从那里构建?

答案 8 :(得分:4)

如果您的路径中有TortoiseSVN,并且您位于正确的目录中:

TortoiseProc.exe /command:cleanup /path:"%CD%" /delunversioned /delignored /nodlg /noui

/command:cleanup的TortoiseSVN帮助中描述了这些选项:

  

使用/ noui防止弹出结果对话框   要么告诉清理完成还是显示错误   信息)。 / noprogressui还会禁用进度对话框。 / nodlg   禁用显示清理对话框,用户可以在其中选择   确切应该在清理中完成。可用的操作可以是   使用options / cleanup指定状态清理,/ revert,   / delunversioned,/ delignored,/ refreshshell和/ externals。

答案 9 :(得分:4)

只需在unix-shell上执行:

rm -rf `svn st . | grep "^?" | cut -f2-9 -d' '`

答案 10 :(得分:3)

Subversion 1.9.0引入了删除未版本化项目的选项[1]

foreach($val as $item) {
    foreach($textures as $k => $v) {
        //this will return array index or false if not exists
        $pos = array_search($item, $v);
        if ( $pos !== false )
            echo "  { \"" . $item . "\", \"" . $k . "\", \"".$v[$pos]."\" },\n";
    }
}

[1] https://subversion.apache.org/docs/release-notes/1.9.html#svn-cleanup-options

答案 11 :(得分:3)

svn st --no-ignore  | grep '^[?I]' | sed 's/^[?I]  *//' | xargs -r -d '\n' rm -r

这是一个unix shell命令,用于删除不受subversion控制的所有文件。

注意:

  • st中的svn ststatus的内置别名,即该命令相当于svn status
  • --no-ignore还在状态输出中包含非存储库文件,否则通过.cvsignore等机制忽略 - 因为目标是为构建创建一个干净的起点,这个交换机是必须的< / LI>
  • grep过滤输出,只留下subversion未知的文件 - 以?开头的行列出subversion未知的文件,如果没有--no-ignore选项将被忽略
  • 通过sed
  • 删除文件名前的前缀
  • xargs命令通过-r指示在参数列表为空时不执行rm
  • -d '\n'选项告诉xargs使用换行符作为分隔符,这样命令也适用于带空格的文件名
  • rm -r用于需要删除完整目录(不属于存储库)

答案 12 :(得分:3)

我的C#转换Thomas Watnedals Python脚本:

Console.WriteLine("SVN cleaning directory {0}", directory);

Directory.SetCurrentDirectory(directory);

var psi = new ProcessStartInfo("svn.exe", "status --non-interactive");
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.WorkingDirectory = directory;

using (var process = Process.Start(psi))
{
    string line = process.StandardOutput.ReadLine();
    while (line != null)
    {
        if (line.Length > 7)
        {
            if (line[0] == '?')
            {
                string relativePath = line.Substring(7);
                Console.WriteLine(relativePath);

                string path = Path.Combine(directory, relativePath);
                if (Directory.Exists(path))
                {
                    Directory.Delete(path, true);
                }
                else if (File.Exists(path))
                {
                    File.Delete(path);
                }
            }
        }
        line = process.StandardOutput.ReadLine();
    }
}

答案 13 :(得分:3)

如果您正在使用togoise svn,则有一个隐藏命令可以执行此操作。在右键单击文件夹的同时保持移位以在Windows资源管理器中启动上下文菜单。您将获得“删除无版本项目”命令。

请参阅此page的底部以获取详细信息,或者下面的屏幕截图突出显示绿色星星的扩展功能,以及黄色矩形感兴趣的功能......

SVN Extended context menu vs standard menu

答案 14 :(得分:2)

svn status --no-ignore | awk '/^[I\?]/ {system("echo rm -r " $2)}'

如果确定要执行的操作,请删除回声。

答案 15 :(得分:2)

如果没有额外的依赖关系,我无法获得上述任何功能,我不想在win32上添加到我的自动构建系统。所以我把以下的Ant命令放在一起 - 请注意这些命令需要安装Ant-contrib JAR(我使用的是版本1.0b3,最新版本的Ant 1.7.0)。

请注意,这会在没有警告的情况下删除所有未版本控制的文件。

  <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
  <taskdef name="for" classname="net.sf.antcontrib.logic.ForTask" />

  <macrodef name="svnExecToProperty">
    <attribute name="params" />
    <attribute name="outputProperty" />
    <sequential>
      <echo message="Executing Subversion command:" />
      <echo message="  svn @{params}" />
      <exec executable="cmd.exe" failonerror="true"
            outputproperty="@{outputProperty}">
        <arg line="/c svn @{params}" />
      </exec>
    </sequential>
  </macrodef>

  <!-- Deletes all unversioned files without warning from the 
       basedir and all subfolders -->
  <target name="!deleteAllUnversionedFiles">
    <svnExecToProperty params="status &quot;${basedir}&quot;" 
                       outputProperty="status" />
    <echo message="Deleting any unversioned files:" />
    <for list="${status}" param="p" delimiter="&#x0a;" trim="true">
      <sequential>
        <if>
          <matches pattern="\?\s+.*" string="@{p}" />
          <then>
            <propertyregex property="f" override="true" input="@{p}" 
                           regexp="\?\s+(.*)" select="\1" />
            <delete file="${f}" failonerror="true" />
          </then>
        </if>
      </sequential>
    </for>
    <echo message="Done." />
  </target>

对于其他文件夹,请更改${basedir}参考。

答案 16 :(得分:2)

因为其他人都在这样做......

svn status | grep ^? | awk '{print $2}' | sed 's/^/.\//g' | xargs rm -R

答案 17 :(得分:1)

纯windows cmd / bat解决方案:

@echo off

svn cleanup .
svn revert -R .
For /f "tokens=1,2" %%A in ('svn status --no-ignore') Do (
     If [%%A]==[?] ( Call :UniDelete %%B
     ) Else If [%%A]==[I] Call :UniDelete %%B
   )
svn update .
goto :eof

:UniDelete delete file/dir
if "%1"=="%~nx0" goto :eof
IF EXIST "%1\*" ( 
    RD /S /Q "%1"
) Else (
    If EXIST "%1" DEL /S /F /Q "%1"
)
goto :eof

答案 18 :(得分:1)

我在RH5机器上偶然发现了svn-clean。它位于/ usr / bin / svn-clean

http://svn.apache.org/repos/asf/subversion/trunk/contrib/client-side/svn-clean

答案 19 :(得分:1)

不妨提供另一种选择

svn status | awk '{if($2 !~ /(config|\.ini)/ && !system("test -e \"" $2 "\"")) {print $2; system("rm -Rf \"" $2 "\"");}}'

/(config | .ini)/是出于我自己的目的。

将-no-ignore添加到svn命令

可能是个好主意

答案 20 :(得分:1)

我在Seth Reno's尝试了this answer版本,但它对我不起作用。我在文件名之前有8个字符,而在cut -c9-中没有使用9个字符。

所以这是我的版本sed而不是cut

svn status | grep ^\? | sed -e 's/\?\s*//g' | xargs -d \\n rm -r

答案 21 :(得分:1)

如果你对powershell很酷:

svn status --no-ignore | ?{$_.SubString(0,1).Equals("?")} | foreach { remove-item -Path (join-Path .\ $_.Replace("?","").Trim()) -WhatIf }

取出-WhatIf标志以使命令实际执行删除。否则,如果在没有-WhatIf的情况下运行,它将只输出 所做的事情。

答案 22 :(得分:1)

我会将此作为评论添加到Thomas Watnedal's answer ,但还不能。

它的一个小问题(不会影响Windows)是它只检查文件或目录。对于可能存在符号链接的Unix系统,有必要更改这一行:

if os.path.isfile(fullpath) or os.path.islink(fullpath):

if match: removeall(match.group(1))

也删除链接。

对我来说,将最后一行 if match: print "Removing " + match.group(1) removeall(match.group(1)) 更改为

?[\?ID]

这样它显示删除的内容也很有用。

根据用例,正则表达式的?[\?I]部分可能会更好D,因为D还会删除受版本控制的已删除文件。我想使用它来构建一个干净的签入文件夹,因此不应该有injectTapEventPlugin状态的文件。

答案 23 :(得分:1)

@zhoufei我测试了您的答案,这里是更新版本:

FOR /F "tokens=1* delims= " %%G IN ('svn st %~1 ^| findstr "^?"') DO del /s /f /q "%%H"
FOR /F "tokens=1* delims= " %%G IN ('svn st %~1 ^| findstr "^?"') DO rd /s /q "%%H"
  • 您必须在G和H前面使用两个%标记
  • 切换顺序:首先删除所有文件,然后删除所有目录
  • (可选:)可以在任何目录名称中使用%~1代替我在bat文件中使用的功能,因此%~1首先是输入参数

答案 24 :(得分:0)

在PERL中执行此操作的一种简洁方法是:

#!/usr/bin/perl
use IO::CaptureOutput 'capture_exec'

my $command = sprintf ("svn status --no-ignore | grep '^?' | sed -n 's/^\?//p'");

my ( $stdout, $stderr, $success, $exit_code ) = capture_exec ( $command );
my @listOfFiles = split ( ' ', $stdout );

foreach my $file ( @listOfFiles )
{ # foreach ()
    $command = sprintf ("rm -rf %s", $file);
    ( $stdout, $stderr, $success, $exit_code ) = capture_exec ( $command );
} # foreach ()

答案 25 :(得分:0)

我用了大约3个小时来生成这个。在Unix中完成它需要5分钟。 主要问题是:Win文件夹名称中的空格,编辑%% i的不可能性以及在Win cmd循环中定义变量的问题。

setlocal enabledelayedexpansion

for /f "skip=1 tokens=2* delims==" %%i in ('svn status --no-ignore --xml ^| findstr /r "path"') do (
@set j=%%i
@rd /s /q !j:~0,-1!
)

答案 26 :(得分:0)

对于那些喜欢用perl而不是python,Unix shell,java等做这个的人。这里有一个小的perl脚本也可以用来做。这就是

注意:这也会删除所有未版本控制的目录

#!perl

use strict;

sub main()

{

    my @unversioned_list = `svn status`;

    foreach my $line (@unversioned_list)

    {

        chomp($line);

        #print "STAT: $line\n";

        if ($line =~/^\?\s*(.*)$/)

        {

            #print "Must remove $1\n";

            unlink($1);

            rmdir($1);

        }

    }

}

main();

答案 27 :(得分:0)

上面的C#代码snipet对我不起作用 - 我有tovise svn客户端,并且行格式略有不同。这是与上面相同的代码snipet,只是重写为函数和使用正则表达式。

        /// <summary>
    /// Cleans up svn folder by removing non committed files and folders.
    /// </summary>
    void CleanSvnFolder( string folder )
    {
        Directory.SetCurrentDirectory(folder);

        var psi = new ProcessStartInfo("svn.exe", "status --non-interactive");
        psi.UseShellExecute = false;
        psi.RedirectStandardOutput = true;
        psi.WorkingDirectory = folder;
        psi.CreateNoWindow = true;

        using (var process = Process.Start(psi))
        {
            string line = process.StandardOutput.ReadLine();
            while (line != null)
            {
                var m = Regex.Match(line, "\\? +(.*)");

                if( m.Groups.Count >= 2 )
                {
                    string relativePath = m.Groups[1].ToString();

                    string path = Path.Combine(folder, relativePath);
                    if (Directory.Exists(path))
                    {
                        Directory.Delete(path, true);
                    }
                    else if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                }
                line = process.StandardOutput.ReadLine();
            }
        }
    } //CleanSvnFolder

答案 28 :(得分:0)

对于那些希望避免使用除标准MS-Dos命令之外的任何工具的Windows上的人员,这里有一个解决方案:

FOR / F&#34;令牌= 1 * delims =&#34; %G IN(&#39; svn st ^ | findstr&#34; ^?&#34;&#39;)DO rd / s / q&#34;%H&#34;

FOR / F&#34;令牌= 1 * delims =&#34; %G IN(&#39; svn st ^ | findstr&#34; ^?&#34;&#39;)DO del / s / f / q&#34;%H&#34;

  • svn st将显示工作副本中每个文件和文件夹的状态
  • findstr会查找以&#39;?&#39;开头的每一行,这意味着文件/文件夹是无版本的
  • FOR将用作分隔符并在第一个之后取代码(第一个是%G,其余是%H) 这样我们就可以从svn st命令输出中提取文件/文件夹。
  • rd将删除文件夹,del将删除文件。

答案 29 :(得分:0)

如果您不想编写任何代码,来自svn2svn的svn2.exe执行此操作,还有an article如何实现它。已删除的文件夹和文件将放入回收站。

运行“svn2.exe sync [path]”。

答案 30 :(得分:0)

我还发现并使用了以下内容: svn status --no-ignore | awk&#39; / ^?/ {print $ 2}&#39; | xargs rm

答案 31 :(得分:0)

使用TortoiseSVN:*右键单击工作副本文件夹,同时按住shift键,选择“删除无版本项目”

How can I delete all unversioned/ignored files/folders in my working copy?