Subversion 버전이 지정되지 않은 파일 자동 제거


111

누구든지 버전 제어를받지 않는 작업 복사본의 모든 파일을 재귀 적으로 제거하는 방법을 알고 있습니까? (자동 빌드 VMware에서 더 안정적인 결과를 얻으려면 이것이 필요합니다.)


7
저는 SVN 사용자이며 Git을 SVN과 비교하여 결국 전환을 원하는지 확인했습니다. 이것은 Git이 "git clean"명령으로 빛나는 또 다른 예일 수 있습니다.
— jpierson

3
또는 hg purge --allMercurial에서.
— Brendan Long

의 중복 stackoverflow.com/questions/2803823/... 더 많은 유용한 활동이 어디.
— Heath Raftery

답변:


26

편집하다:

Subversion 1.9.0은이를위한 옵션을 도입했습니다 :

svn cleanup --remove-unversioned

그 전에이 파이썬 스크립트를 사용하여 다음을 수행합니다.

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

일을 꽤 잘하는 것 같습니다.


1
Python 2.7.2에서 여전히 작동합니다. Warren P : 더 자세한 정보를 제공 할 수 있습니까?
— Thomas Watnedal 2014-06-23

파이썬 2.6의 문제라고 생각합니다. 2.7에서 다시 작동합니다.
— Warren P

1
Downvote : 벨로우즈의 다른 솔루션 svn cleanup --remove-unversioned이 더 좋습니다. 그리고 그것은 Subversion 1.9.0 용입니다 (이 버전은 2015 년부터입니다). 안정적이고 표준입니다.
— tres.14159

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 이상을 사용하는 경우 --remove-unversioned 및 --remove-ignored 옵션과 함께 svn cleanup 명령을 사용하면됩니다.


6
cygwin의 Windows에서도 사용할 수 있습니다.
— Honza

9
공백이있는 파일 이름의 경우 xargs에 -d 옵션을 추가하고 추가 된 디렉토리의 경우 rm에 -r 옵션을 추가하는 것을 고려할 수 있습니다. svn status | grep ^ \? | 컷 -c9- | xargs -d \\ n rm -r
— Seth Reno

4
또한 OS X에서 실행되는 -d 옵션에 문제가있었습니다. 대안은 다음과 같습니다.이 옵션은 줄 바꿈을 null 문자로 변환하고 xargs에서 -0 옵션을 사용하여 파일 이름의 공백을 처리합니다. svn status | grep ^ \? | 컷 -c9- | tr '\ n' '\ 0'| xargs -0 rm
— Brian Webster

3
다른 명령의 출력에서 ​​정확한 문자 수에 의존하는 명령에 눈살을 찌푸린 경우 :svn status | grep "^?" | awk '{print $2}' | xargs -d \\n rm -r
— Michael Schlottke-Lakemper 2013-04-25

3
xargs 커맨드를 살펴 보자 @Pavel --no-실행하면 빈 옵션
— 켄

71

자동화 된 빌드는 아니지만 동일한 작업을 수행하는 동안이 페이지를 살펴 보았습니다.

좀 더 살펴본 후 TortoiseSVN에서 ' 확장 컨텍스트 메뉴 '를 발견했습니다 . Shift 키를 누른 상태에서 작업 복사본을 마우스 오른쪽 버튼으로 클릭합니다. 이제 TortoiseSVN 메뉴 아래에 ' 버전이 지정되지 않은 항목 삭제 ... '를 포함한 추가 옵션이 있습니다 .

이 특정 질문에는 해당되지 않을 수도 있지만 (즉, 자동화 된 빌드의 맥락에서) 동일한 작업을 수행하려는 다른 사람들에게 도움이 될 것이라고 생각했습니다.


큰! XP에서는 트리보기 (왼쪽)가 아닌 목록보기 (탐색기 오른쪽)에서만 작동합니다.
— Christopher Oezbek

환상적이며 휴지통으로 만 보내면 바로 삭제하는 것이 좋습니다. 내가 필요한 것만.
— 딘 토마스

TortoiseSVN의 TortoiseProc.exe를 사용하여 명령 줄에서이를 자동화 할 수도 있습니다. 자세한 내용은 아래 답변에 있습니다.
— stevek_mcc


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"

1
이것은 나를 위해 다소 일했습니다. 하지만 버전이 지정되지 않은 일부 폴더에서 질식하는 것 같습니다.
— jpierson

7

내 Windows powershell 프로필에 이것을 추가했습니다.

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

2
@FelipeAlvarez 네. 응 우리는 그래. 얇게 썬 빵 이후 가장 좋은 것은 아니지만 배치를 능가합니다. .NET 어셈블리를 가져올 수 있기 때문에 적어도 bash만큼 유용하다고 말하고 싶습니다.
— jpmc26

그것은 마이크로 소프트의 장황함을 향한 끔찍한 경향 (명령 이름 길이뿐만 아니라 인터넷에서 거대한 스 니펫을 복사하지 않고는 무엇이든 할 수있는 전반적인 불가능 함)을 겪고 있지만, 놀랍게도 유용하고 잘 생각합니다.
— Warren P

1
당신은 추가 할 수 있습니다 --no-ignore에 svn status와 -Recurse에Remove-Item
— 케빈 스미스

5

Linux 명령 줄 :

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

또는 일부 파일이 루트 소유인 경우 :

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

이것은 Ken의 대답을 기반으로합니다. (Ken의 대답은 무시 된 파일을 건너 뛰고 내 대답은 파일을 삭제합니다).


5

다음을 사용하여 유닉스 쉘에서 수행하십시오.

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

삭제할 파일 수가 최대 명령 줄 인수 수를 초과하면 작동하지 않습니다. xargs 기반 답변도 참조하십시오.
— maxschlepzig

4

새로운 위치로 내보내고 거기에서 빌드 할 수 없습니까?


1
자동화 된 빌드의 경우 깨끗한 내보내기를 원합니다.
— g.

1
이상적으로는이 작업을 수행하지만 결제가 매우 큰 경우 문제가됩니다. 이것이 OP가 요청한 이유 일 것입니다. 빌드를 더 짧게 만들기 위해.
— jpmc26

4

당신이 만약 TortoiseSVN을을 경로와 당신이 바로 그 디렉토리에 있습니다 :

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

옵션은 다음에 대한 TortoiseSVN 도움말에 설명되어 있습니다 /command:cleanup.

/ noui를 사용하여 정리가 완료되었음을 알리거나 오류 메시지를 표시하는 결과 대화 상자가 팝업되지 않도록합니다. / noprogressui는 진행률 대화 상자도 비활성화합니다. / nodlg는 사용자가 정리에서 정확히 수행해야 할 작업을 선택할 수있는 정리 대화 상자를 표시하지 않습니다. 사용 가능한 작업은 상태 정리, / revert, / delunversioned, / delignored, / refreshshell 및 / externals에 대한 / cleanup 옵션으로 지정할 수 있습니다.


4

tortoise svn을 사용하는 경우이를 수행하는 숨겨진 명령이 있습니다. Windows 탐색기에서 상황에 맞는 메뉴를 시작하려면 Shift 키를 누른 채 폴더를 마우스 오른쪽 버튼으로 클릭합니다. "버전이 지정되지 않은 항목 삭제"명령이 표시됩니다.

자세한 내용은이 페이지 하단을 참조 하거나 확장 기능을 녹색 별표로 표시하고 관심 항목을 노란색 사각형으로 강조 표시 한 아래 스크린 샷을 참조하십시오.

SVN 확장 컨텍스트 메뉴 대 표준 메뉴



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();
    }
}

나중에 필요할 경우를 대비하여 버전이 지정되지 않은 파일을 옮기고 싶습니다.
— leppie

물론 개발 시스템에서는-하지만 VMware 빌드에서는 아무도 그것에 로그온하여 파일을 생성하지 않기 때문에 말이되지 않습니다.
— Stefan Schultze

감사합니다. 나는 이것을 cruisecontrol에서 MSBuild 스크립트의 일부로 사용하여 빌드하기 전에 소스 디렉토리를 정리했습니다.
— gregmac

코드를 기반으로 시작하여 한 단계 더 나아갔습니다. github.com/tgmayfield/svn-clean-sharp/downloads
— Tom Mayfield

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

이것은 Subversion 제어하에 있지 않은 모든 파일을 삭제하는 유닉스 쉘 명령입니다.

노트:

  • st에서이 svn st빌드에 대한 별칭 status, 즉 명령에 해당svn status
  • --no-ignore또한 상태 출력에 비 저장소 파일을 포함하고 그렇지 않으면 .cvsignore등의 메커니즘을 통해 무시합니다 .-목표는 빌드를위한 깨끗한 시작점을 갖는 것이므로이 스위치는 필수입니다.
  • grep전복에 그와 같은 출력은 알 수없는 파일 필터는 남아 있습니다 - 라인은로 시작 ?를 빼고 무시 될 것이다 전복에 대한 목록 파일의 알 수없는 --no-ignore옵션
  • 파일 이름까지의 접두사는 다음을 통해 제거됩니다. sed
  • xargs명령을 통해 지시를 -r실행하지에 rm인수 목록이 비어 될 때,
  • 이 -d '\n'옵션은 xargs줄 바꿈을 구분자로 사용하도록 지시 합니다. 이러한 명령은 공백이있는 파일 이름에도 작동합니다.
  • rm -r 저장소의 일부가 아닌 전체 디렉토리를 제거해야하는 경우에 사용됩니다.

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}참조를 변경하십시오 .


1
참고 : 버전이 지정되지 않은 파일 만 삭제합니다. 버전이 지정되지 않은 빈 폴더는 제거하지 않습니다.

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

당신이 원하는 것이 확실하다면 에코를 제거하십시오.


1
n이 삭제 된 파일에 대해 n /bin/sh및 n 개의 rm프로세스가 분기 되기 때문에 xargs 기반 응답보다 열등합니다 .
— maxschlepzig

동의합니다. xargs 정보에 감사드립니다.
— Aria

2

다들하고 있으니까 ...

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

1

다른 옵션을 제공 할 수도 있습니다.

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

/(config|.ini)/는 내 목적을위한 것입니다.

svn 명령에 --no-ignore를 추가하는 것이 좋습니다.



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

사실이 스크립트는 내 파일을 삭제하지 않았습니다. 공백 때문일 수 있습니다. @SukeshNambiar의 한 줄 답변이 작동했습니다.
— Christiaan Westerbeek

1

이 답변 에서 Seth Reno의 버전을 시도했지만 저에게 효과가 없었습니다. 나는 파일 이름 앞에 8자를 사용했으며 .cut -c9-

그래서 이것은 sed대신 내 버전 입니다 cut.

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

1

powershell이 ​​멋지다면 :

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

명령이 실제로 삭제를 수행하도록하려면 -WhatIf 플래그를 제거하십시오. 그렇지 않으면 -WhatIf없이 실행할 경우 수행 할 작업을 출력합니다 .


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]는 AS, D또한 제거합니다 버전의 통제하에 있었다 파일을 삭제. 나는 이것을 사용하여 깨끗한 체크 인 폴더에 빌드하고 싶으므로 D상태에 파일이 없어야합니다 .


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첫 번째 입력 매개 변수입니다.


0

파이썬, 유닉스 쉘, 자바 등 대신에 펄로 이것을하기를 좋아하는 사람들을 위해. 이로써 지브도 수행하는 작은 펄 스크립트가있다.

참고 : 이렇게하면 버전이 지정되지 않은 모든 디렉토리도 제거됩니다.

#!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();


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

0

나는 이것을 생성하기 위해 ~ 3 시간을 사용했다. Unix에서는 5 분 정도 걸립니다. 주요 문제는 Win 폴더 이름의 공백, %% i 편집 불가능 및 Win cmd 루프에서 vars 정의 문제였습니다.

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

0

위의 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.