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-ignoresvn status-RecurseRemove-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.