145

In SVN is there a command I can use to delete all locally missing files in a directory?

Or failing that, some way of listing only those files that are missing (or, in the more general case, have status A, D, ?, etc.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
wheresrhys
  • 22,558
  • 19
  • 94
  • 162
  • 1
    I maintain 1 working folder, and 1 checkout folder. And move only files from working folder to the check out folder. If a folder must be added/removed, I do it manually and then move files into that folder (for example new packages, old packages). Most svn issues happen when you move folders on your working copy. Even when coping files from your working copy to checkout copy, you should only move files, not folders. – Siddharth Mar 09 '12 at 05:37

12 Answers12

186

If you're using Mac (Darwin) or Linux you can pipe the outputs of the following commands to svn rm for all missing files. You can set the current working directory to the appropriate directory or subdirectory before running these - dependent on whether you want to run this your entire working copy, or only a subset.

  1. Run an svn status
  2. Search for lines that begin with "!" (missing)
  3. Print the "--force" (svn argument) and the second column (the file name) of the output from #2
  4. Run svn rm using the output of #3 as arguments

So the full command is:

svn st | grep ^! | awk '{print " --force "$2}' | xargs svn rm

References:

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Peter Ajtai
  • 56,972
  • 13
  • 121
  • 140
  • 4
    This doesn't work if there are spaces in the file name. I don't know enough awk to fix it, though. – bugloaf Oct 08 '13 at 15:34
  • @bugloaf - thanks for the heads up - think you'd have to incorporate some sort of loop to get all columns 2+ - something like http://stackoverflow.com/a/7918051/186636 - not sure exactly - I'll try to play around with it at some point – Peter Ajtai Oct 08 '13 at 18:33
  • 4
    Use `awk '{print " --force "$2"@"}'` if your filename contains a `@` (if you're an iOS dev for example) – Guillaume Algis Nov 21 '13 at 16:35
  • 1
    And handle a filename with whitespace(s), `awk '{$1=""; print " --force \""substr($0,2)"@\"" }'` should do the trick (and begins to look ugly) – Guillaume Algis Nov 21 '13 at 16:42
  • Here's another option for handling files with whitespace (the \x22 prints a straight double-quote): delete - `svn status | grep ^! | awk -F '       ' '{print " \x22"$2"\x22"}' | xargs svn delete`, add - `svn status | grep ^? | awk -F '       ' '{print " \x22"$2"\x22"}' | xargs svn add`. Note that's seven spaces in the `-F` argument. – Nick Williams Nov 25 '13 at 22:02
  • 14
    The full command taking care of the space is "svn st | grep ^! | awk '{$1=""; print " --force \""substr($0,2)"@\"" }' | xargs svn rm" – ABCD Jan 03 '14 at 01:27
  • 4
    Why don't you put the `--force` into the xargs part? – jwg Feb 21 '14 at 17:25
  • Under windows and cygwin use: svn st | grep ^! | awk '{gsub(/\\/, "/");print " --force \""$2"\""}' | xargs svn rm (gsub to replace / with \; filename with in " to work with whitespaces) – leo Apr 16 '15 at 08:02
  • This is pretty great! thanks everyone. It can be VERY easily modified to work for newly added files by changing the `^!` to `^?` – Tony Adams Aug 19 '15 at 19:42
  • 1
    This filename hack is so terrible, stop using this old 1970th unix hacks, it does not work with all possible file names that require more complex escapes. – Lothar May 22 '18 at 13:54
  • 1
    I stopped using SVN. – Peter Ajtai May 25 '18 at 00:00
  • @Lothar, right... `svn status --xml` would be a better start for the pipeline. – David L. Mar 10 '21 at 10:15
109

If you are using TortoiseSVN, just do a Check for Modifications, sort by the Status column, select all the entries marked missing, right-click to open the context menu, and select Delete. Finally, commit to publish the changes to the repository.

If you are on Windows, but prefer the command-line and enjoy dabbling in PowerShell, this one-liner will do the trick:

svn status | ? { $_ -match '^!\s+(.*)' } | % { svn rm $Matches[1] }

That is, filter the output to only those lines showing missing files (denoted by an exclamation at the start of the line), capture the associated file name, and perform an svn rm on that file name.

(Blog post Remove all “missing” files from a SVN working copy does something similar for Unix/Linux.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Michael Sorens
  • 35,361
  • 26
  • 116
  • 172
  • is there a way in eclipse using subclipse plugin? it is so bad to update a then find them in project and delete them again. – Stan May 29 '14 at 06:41
  • FYI, if a subversion password is needed here is the syntax: svn status --username user_name_here --password password_here | ? { $_ -match '^!\s+(.*)' } | % { svn rm $Matches[1] --username user_name_here--password password_here } – Jeff Sep 26 '16 at 14:03
  • should you first commit after this line before executing `svn up` ? because the files are restored from the svn server – Pierre Oct 23 '18 at 09:38
  • Will this action delete the files from the repository too? – Sebastián Ulloa Feb 05 '19 at 18:08
65
svn st | grep ! | cut -d! -f2| sed 's/^ *//' | sed 's/^/"/g' | sed 's/$/"/g' | xargs svn rm
  1. svn status
  2. Filter only on missing files
  3. Cut out exclamation point
  4. Filter out trailing whitespaces
  5. Add leading quote
  6. Add trailing quote
  7. svn remove each file
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ivrin
  • 1,707
  • 1
  • 14
  • 11
  • This solution works if there are spaces in the files/directories. – yuric Jan 21 '16 at 18:43
  • How does one add verbosity to this? xargs -verbose svn rm ? – TechFanDan May 09 '17 at 14:52
  • 1
    Just a hint for users of scripts etc., this command fails if no files to delete are found: svn: E205001: Try 'svn help delete' for more information svn: E205001: Not enough arguments provided – Thorsten Schöning Jul 09 '17 at 10:42
  • 2
    @ThorstenSchöning's problem can be fixed by adding `-r` to the `xargs` options (do not run, if nor arguments are given). Additionally, the numer of arguments should be limited and removals should be batched because the invocation fails with very large number of files to remove, e.g. `-n 500`. And last but not least, the quoting performed is suboptimal for files containing shell specials like `$` - better use `\n` as delimiter and leave quoting to `xargs`: `svn status | grep "!" | cut -d! -f2 | sed 's/^ *//' | xargs -n 500 -d "\n" -r svn rm` – haui Jun 09 '20 at 06:35
32

I just found this, which does the trick, Remove all “missing” files from a SVN working copy:

svn rm $( svn status | sed -e '/^!/!d' -e 's/^!//' )
brasofilo
  • 25,496
  • 15
  • 91
  • 179
wheresrhys
  • 22,558
  • 19
  • 94
  • 162
22

Thanks to Paul Martin for the Windows version.

Here is a slight modification to the script so Windows files with spaces are taken into account as well. Also the missing.list file will be removed at the end.

I saved the following in svndel.bat in my SVN bin directory (set in my %%PATH environment) so it can be called from any folder at the command prompt.

### svndel.bat
svn status | findstr /R "^!" > missing.list
for /F "tokens=* delims=! " %%A in (missing.list) do (svn delete "%%A")
del missing.list 2>NUL
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user3689460
  • 229
  • 2
  • 2
  • nice to see some innovative batch code still appearing :) – user230910 Sep 25 '17 at 09:04
  • Wow, great answer. I was about to go with powershell, but this was so much easier. – Jim Andrakakis Jan 26 '18 at 15:21
  • I added another line after `del missing.list 2>NUL`, because I added all new files directly after first removing the deleted files so it added `missing.list` to svn: `svn delete "missing.list"` worked for me – Pierre Oct 24 '18 at 06:33
  • I had modified this script to attempt to run from an arbitrary location then encountered this issue https://stackoverflow.com/questions/1137219/aptana-1-5-svn-error-resolving-case-of/1137297#1137297 so it appears you MUST use the Current Working Directory to perform this action. – aolszowka Dec 02 '19 at 17:10
8

I like the PowerShell option... But here's another option if you're using Windows batch scripts:

svn status | findstr /R "^!" > missing.list
for /F "tokens=2 delims= " %%A in (missing.list) do (svn delete %%A)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Paul Martin
  • 316
  • 3
  • 5
8

It is actually possible to completely remove the missing.list from user3689460 and Paul Martin

for /F "tokens=* delims=! " %%A in ('svn status ^| findstr /R "^!"') do (svn delete "%%A")
Amfasis
  • 3,932
  • 2
  • 18
  • 27
6

An alternative that works on Linux (bash) for to-be-removed files not containg spaces in path:

svn delete `svn status | grep ! | awk '{print $2}'`
gilyen
  • 81
  • 1
  • 4
5

This shell script, recursively examines (svn status) directories in your project, removing missing files (as the question demands) and adding new files to the repository. It is some sort of "store into the repository the current snapshot of the project".

if [ $# != 1 ]
then
    echo  "usage: doSVNsnapshot.sh DIR"
    exit 0
fi

ROOT=$1

for i in `find ${ROOT} -type d \! -path "*.svn*" `
do

    echo
    echo "--------------------------"
    ( cd $i ; 
    echo $i
    echo "--------------------------"


    svn status | awk '  
            /^[!]/ { system("svn rm " $2) }
            /^[?]/ { system("svn add " $2) }
        '
    )
    echo

done
cibercitizen1
  • 20,944
  • 16
  • 72
  • 95
5

A slight modification of the command line, which works on Mac OS (hopefully even on Linux) and copes with the files the command "svm sr" reports, like "!M" (missing and modified).

It copes with spaces in the files.

It is based on a modification of a previous answer:

svn st | grep ! | sed 's/!M/!/' | cut -d! -f2| sed 's/^ *//' | sed 's/^/"/g' | sed 's/$/"/g' | xargs svn --force rm
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Stefano Bossi
  • 51
  • 1
  • 4
3

When dealing with a lot of files, it can happen that the argument input to xargs is getting too long. I went for a more naive implementation which works in that case, too.

This is for Linux:

#! /bin/bash
# 1. get all statii in the working copy
# 2. filter out only missing files
# 3. cut off the status indicator (!) and only return filepaths
MISSING_PATHS=$(svn status $1 | grep -E '^!' | awk '{print $2}')
# iterate over filepaths
for MISSING_PATH in $MISSING_PATHS; do
    echo $MISSING_PATH
    svn rm --force "$MISSING_PATH"
done
Jonas Eberle
  • 2,835
  • 1
  • 15
  • 25
3

Improved Version

So the full command is:

svn st | grep ^! | sed 's/![[:space:]]*//' |tr '\n' '\0' | xargs -0 svn --force rm
Zeta
  • 65
  • 4
  • The part "sed 's/![[:space:]]*//'" should read "sed 's/^![[:space:]]*//'" (notice the extra caret "^") so that it only matches "!" + spaces at the beginning of each line and not in the middle. – stux Oct 09 '21 at 16:49