114

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

4

32 回答 32

141

这在 bash 中对我有用:

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

Seth Reno的更好:

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

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

根据下面的评论,这只适用于颠覆不知道的文件(状态=?)。subversion知道的任何东西(包括忽略的文件/文件夹)都不会被删除。

如果您使用的是 subversion 1.9 或更高版本,您可以简单地使用带有 --remove-unversioned 和 --remove-ignored 选项的svn cleanup命令

于 2008-10-27T08:52:13.277 回答
71

我在想做同样的事情时遇到了这个页面,虽然不是为了自动构建。

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

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

于 2009-06-30T14:59:38.450 回答
30

编辑:

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))

它似乎很好地完成了这项工作。

于 2008-10-27T08:46:27.547 回答
19

参见:svn-clean

于 2009-11-24T12:44:28.167 回答
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"
于 2009-10-01T07:19:17.567 回答
7

我将此添加到我的 Windows PowerShell 配置文件中

function svnclean {
    svn status | foreach { if($_.StartsWith("?")) { Remove-Item $_.substring(8) -Verbose } }
}
于 2011-08-31T01:34:13.523 回答
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 的回答跳过了被忽略的文件;我的回答删除了它们)。

于 2011-05-24T14:30:10.307 回答
5

只需在 unix-shell 上执行以下操作:

rm -rf `svn st . | grep "^?" | cut -f2-9 -d' '`
于 2013-07-05T14:31:02.280 回答
4

您不能只导出到新位置并从那里构建吗?

于 2008-10-27T08:41:02.910 回答
4

如果您使用的是 tortoise svn,则有一个隐藏命令可以执行此操作。按住 shift 同时右键单击文件夹以在 Windows 资源管理器中启动上下文菜单。您将获得“删除未受版本控制的项目”命令。

有关详细信息,请参阅本页底部,或下面的屏幕截图,其中以绿色星标突出显示扩展功能,并以黄色矩形突出显示感兴趣的功能...

SVN 扩展上下文菜单与标准菜单

于 2010-08-16T12:00:19.040 回答
4

如果你的路径上有TortoiseSVN并且你在正确的目录中:

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

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

使用 /noui 防止结果对话框弹出,告诉您清理已完成或显示错误消息)。/noprogressui 也禁用进度对话框。/nodlg 禁用显示清理对话框,用户可以在该对话框中选择在清理中应该执行的确切操作。可以使用选项 /cleanup 为状态清除、/revert、/delunversioned、/delignored、/refreshshell 和 /externals 指定可用的操作。

于 2016-09-14T21:33:19.363 回答
4

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

svn cleanup --remove-unversioned

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

于 2018-08-11T18:36:57.173 回答
3

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

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();
    }
}
于 2008-10-27T09:01:53.960 回答
3
svn st --no-ignore  | grep '^[?I]' | sed 's/^[?I]  *//' | xargs -r -d '\n' rm -r

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

笔记:

  • stin是的svn st内置别名status,即命令等价于svn status
  • --no-ignore在状态输出中还包括非存储库文件,否则通过诸如此类的机制忽略.cvsignore- 因为目标是为构建有一个干净的起点,所以这个开关是必须的
  • grep过滤输出,以便只留下 subversion 未知的文件 - 以列表文件开头的行subversion?将在没有--no-ignore选项的情况下被忽略
  • 文件名的前缀是通过sed
  • 当参数列表为空时,命令xargs通过指示-r不执行rm
  • -d '\n'选项告诉xargs使用换行符作为分隔符,这样该命令也适用于带空格的文件名
  • rm -r用于需要删除完整目录(不是存储库的一部分)的情况
于 2014-07-22T20:52:38.753 回答
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}参考。

于 2009-04-23T12:16:30.140 回答
2
svn status --no-ignore | awk '/^[I\?]/ {system("echo rm -r " $2)}'

如果您确定要做什么,请删除回声。

于 2010-12-31T20:20:52.327 回答
2

因为其他人都在做...

svn status | grep ^? | awk '{print $2}' | sed 's/^/.\//g' | xargs rm -R
于 2013-05-30T15:01:16.953 回答
1

不妨贡献另一种选择

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

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

将 --no-ignore 添加到 svn 命令可能是个好主意

于 2012-03-28T22:35:07.713 回答
1

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

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

于 2012-04-17T21:59:51.060 回答
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
于 2012-12-22T23:00:25.977 回答
1

我已经从这个答案中尝试了Seth Reno 的版本,但它对我没有用。我在文件名之前有 8 个字符,而不是.cut -c9-

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

svn status | grep ^\? | sed -e 's/\?\s*//g' | xargs -d \\n rm -r
于 2014-01-29T20:01:09.797 回答
1

如果您对 powershell 很满意:

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

取出 -WhatIf 标志以使命令实际执行删除。否则,它只会输出在没有 -WhatIf 的情况下运行时会执行的操作。

于 2015-02-06T03:53:02.377 回答
1

我会将其添加为对Thomas Watnedal 答案的评论,但目前还不能。

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

if os.path.isfile(fullpath):

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状态。

于 2017-05-26T10:22:04.717 回答
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是第一个输入参数
于 2018-08-08T14:59:11.033 回答
0

对于喜欢使用 perl 而不是 python、Unix shell、java 等的人。特此提供一个小的 perl 脚本,它也可以执行 jib。

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

#!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();
于 2009-07-31T12:22:18.590 回答
0

如果您不想编写任何代码,svn2svn 的svn2.exe会执行此操作,还有一篇关于如何实现的文章。删除的文件夹和文件被放入回收站。

运行“svn2.exe 同步 [路径]”。

于 2010-11-02T20:27:57.030 回答
0

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

如何删除工作副本中所有未版本化/忽略的文件/文件夹?

于 2011-04-28T10:17:01.967 回答
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 ()
于 2013-07-31T19:55:40.450 回答
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!
)
于 2014-02-28T11:59:02.200 回答
0

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

        /// <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
于 2014-08-18T03:17:14.797 回答
0

对于想要避免使用除标准 MS-Dos 命令之外的任何工具的 Windows 用户,这里有一个解决方案:

FOR /F "tokens=1* delims=" %G IN ('svn st ^| findstr "^?"') DO rd /s /q "%H"

FOR /F "tokens=1* delims=" %G IN ('svn st ^| findstr "^?"') DO del /s /f /q "%H"

  • svn st 将显示工作副本中每个文件和文件夹的状态
  • findstr 将查找以“?”开头的每一行,这意味着文件/文件夹是未版本控制的
  • FOR 将用作分隔符并取第一个之后的标记(第一个是 %G,其余的是 %H)这样我们从 svn st 命令输出中提取文件/文件夹。
  • rd 将删除文件夹, del 将删除文件。
于 2015-07-13T03:31:58.880 回答
0

我还发现并使用了以下内容:svn status --no-ignore| awk '/^?/ {打印 $2}'| xargs rm

于 2018-01-15T16:04:22.647 回答