代码之家  ›  专栏  ›  技术社区  ›  Stefan Schultze

自动删除Subversion未版本化的文件

  •  115
  • Stefan Schultze  · 技术社区  · 17 年前

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

    32 回复  |  直到 11 年前
        1
  •  139
  •   Community Mohan Dere    9 年前

    这在bash中对我有效:

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

    Seth Reno 的更好:

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

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

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

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

        2
  •  71
  •   g .    17 年前

    我浏览了这个页面,同时想做同样的事情,尽管不是为了自动构建。

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

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

        3
  •  29
  •   Thomas Watnedal    7 年前

    编辑:

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

    它似乎做得很好。

        4
  •  19
  •   zellus    15 年前

    请参阅: svn-clean

        5
  •  9
  •   user1607178 Sukesh Nambiar    13 年前

    如果你在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"
    
        6
  •  7
  •   Sixto Saez    9 年前

    我已将其添加到我的windows powershell配置文件中

    function svnclean {
        svn status | foreach { if($_.StartsWith("?")) { Remove-Item $_.substring(8) -Verbose } }
    }
    
        7
  •  5
  •   user9876    15 年前

    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
    

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

        8
  •  5
  •   Konstantin Burlachenko    13 年前

    只需在unix shell上使用以下命令即可:

    rm -rf `svn st . | grep "^?" | cut -f2-9 -d' '`
    
        9
  •  4
  •   leppie    17 年前

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

    svn cleanup --remove-unversioned
    

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

        10
  •  4
  •   stevek_mcc Mark Wilkins    9 年前

    你不能直接导出到一个新位置并从那里构建吗?

        11
  •  4
  •   jxramos    8 年前

    如果你有 TortoiseSVN 在您的路径上,您位于正确的目录中:

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

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

    使用/noui防止弹出结果对话框 告知清理已完成或显示错误 消息)。/noprogressui还会禁用进度对话框。/nodlg 禁用显示清理对话框,用户可以在其中选择 在清理过程中应该严格执行。可用的操作可以是 使用选项/cleap指定状态清理、/rever、, /delunversion、/redelinored、/refreshshell和/externals。

        12
  •  4
  •   Ivan Zhakov    7 年前

    如果你使用乌龟svn,有一个隐藏的命令可以做到这一点。按住shift键的同时右键单击文件夹,以在windows资源管理器中启动上下文菜单。您将收到“删除未指定项目”命令。

    看看这个的底部 page 有关详细信息,请参阅下面的屏幕截图,其中绿色星星突出显示了扩展功能,黄色矩形突出显示了感兴趣的功能。..

    SVN Extended context menu vs standard menu

        13
  •  3
  •   Stefan Schultze    17 年前

    我对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();
        }
    }
    
        14
  •  3
  •   maxschlepzig    12 年前
    svn st --no-ignore  | grep '^[?I]' | sed 's/^[?I]  *//' | xargs -r -d '\n' rm -r
    

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

    笔记:

    • 这个 st 在……里面 svn st 是的内置别名 status ,即该命令等效于 svn status
    • --no-ignore 状态输出中还包括非存储库文件,否则通过以下机制忽略 .cvsignore 等等-由于目标是为构建提供一个干净的起点,因此必须进行此切换
    • 这个 grep 过滤输出,只留下不被颠覆的文件——以开头的行 ? 列出颠覆未知的文件,如果没有 --不容忽视 选项
    • 文件名之前的前缀将通过以下方式删除 sed
    • 这个 xargs 命令通过以下方式指示 -r 不执行 rm ,当参数列表为空时
    • 这个 -d '\n' 选项告诉 参数代换 使用换行符作为分隔符,该命令也适用于带空格的文件名
    • rm -r 用于需要删除完整目录(不属于存储库)的情况
        15
  •  2
  •   Steve Steve    17 年前

    如果没有我不想添加到win32上的自动构建系统中的额外依赖项,我无法使上述任何一项工作。因此,我组合了以下Ant命令——请注意,这些命令需要安装Ant contrib JAR(我使用的是Ant 1.7.0的最新版本1.0b3)。

    请注意,这会删除所有未版本的文件,而不会发出任何警告。

      <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
  •   Aria    15 年前
    svn status --no-ignore | awk '/^[I\?]/ {system("echo rm -r " $2)}'
    

    如果确定要这样做,请删除回声。

        17
  •  2
  •   josh-cain    13 年前

    既然其他人都在这么做。。。

    svn status | grep ^? | awk '{print $2}' | sed 's/^/.\//g' | xargs rm -R
    
        18
  •  1
  •   JeremyLoffredo    14 年前

    不妨提供另一种选择

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

    /(config|.ini)/是为了我自己的目的。

    在svn命令中添加--no ignore可能是个好主意

        19
  •  1
  •   Eric Cope    14 年前

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

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

        20
  •  1
  •   G. Lombard    12 年前

    纯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
    
        21
  •  1
  •   Community Mohan Dere    9 年前

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

    这是我的版本 sed 而不是 cut :

    svn status | grep ^\? | sed -e 's/\?\s*//g' | xargs -d \\n rm -r
    
        22
  •  1
  •   Giscard Biamby    11 年前

    如果你对powershell很熟悉:

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

    去掉-WhatIf标志,使命令实际执行删除操作。否则,它只会输出它所输出的内容 do if运行时不使用-WhatIf。

        23
  •  1
  •   Michael Firth    9 年前

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

    它的一个小问题(不会影响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 国家。

        24
  •  1
  •   LundinCast    8 年前

    @周飞我测试了你的答案,这里是更新版本:

    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. 是第一个输入参数
        25
  •  0
  •   dB.    15 年前

    如果你不想写任何代码,svn2.exe svn2svn 这样做,还有 an article 关于它是如何实施的。已删除的文件夹和文件会被放入回收站。

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

        26
  •  0
  •   Craig McQueen Dr. Watson    15 年前

    对于喜欢用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();
    
        27
  •  0
  •   Community Mohan Dere    9 年前

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

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

        28
  •  0
  •   J. T. Marsh    13 年前

    在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 ()
    
        29
  •  0
  •   flx    12 年前

    我用了大约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!
    )
    
        30
  •  0
  •   TarmoPikaro    11 年前

    上面的C#代码片段对我不起作用——我有乌龟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
    
    推荐文章