196

One of the missions of an export tool I have in my application, is to clean all .svn directories from my application directory tree. I am looking for a recursive command in the Linux shell that will traverse the entire tree and delete the .svn files.

I am not using export, as this script will be used for some other file/directory names which are not related to SVN. I tried something like:

find . -name .svn | rm -fr

It didn't work...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Itay Moav -Malimovka
  • 52,579
  • 61
  • 190
  • 278
  • 3
    Your command should work if you use 'xargs rm -rf' – heijp06 Aug 18 '09 at 15:22
  • 1
    You might also want to modify the delete command "rm -rfi" just to make sure you are positive you want to delete the directories. – bedwyr Aug 18 '09 at 15:26
  • Don't use xargs though.. you'll have trouble with directories that have spaces in them etc. Use find as described below. – John Hunt Jan 23 '14 at 10:49

11 Answers11

447

Try this:

find . -name .svn -exec rm -rf '{}' \;

Before running a command like that, I often like to run this first:

find . -name .svn -exec ls '{}' \;
siegy22
  • 4,295
  • 3
  • 25
  • 43
Greg
  • 5,656
  • 3
  • 22
  • 19
  • 43
    You may need to put {} into single quote if there may be space or such characters in directories: `find . -name .svn -exec rm -rf '{}' \;` – mtoloo Sep 17 '12 at 11:25
  • 41
    This test works better in my bash : `find . -name .svn -exec echo {} \;` – Fedir RYKHTIK May 06 '13 at 15:46
  • 6
    Running echo / ls first is the 'pro' touch to this answer. Any fool can wreck a system. – John Hunt Jan 23 '14 at 10:44
  • why is using echo better? – Bill Rosmus Sep 26 '14 at 23:29
  • @BillR Because echo will list the directories to removed, where as ls will list their contents. – pamphlet Oct 07 '14 at 15:01
  • 6
    what does the `{} \;` do? – Jon Mitten Apr 29 '15 at 23:53
  • This answer breaks if done in a script, like a makefile. I guess because **find: ./assets/Assets/res/dictionary/3x: No such file or directory** etc is output for me. (did a find on 3x) – Jonny Jul 24 '15 at 04:43
  • can you explain what each of those commands do? I ran the second one and files removed. It rejected to run the first one later?! I thought I have to run both! Is that what should happen? – hasan Jul 29 '15 at 08:23
  • 3
    By running the second command including `ls`, I get `entries prop-base props text-base tmp` output... – Rasoul Oct 26 '15 at 16:37
  • 2
    @Rasoul try @Fedir solution: `find . -name .svn -exec echo {} \;` – Lucas Martins Sep 27 '16 at 05:00
  • `man find`(1) shows a suitable example to detects whether some SCM administrative directories: `find repo/ -exec test -d {}/.svn \; -or -exec test -d {}/.git \; -or -exec test -d {}/CVS \; -print -prune` – bzimage Feb 11 '20 at 10:00
53

What you wrote sends a list of newline separated file names (and paths) to rm, but rm doesn't know what to do with that input. It's only expecting command line parameters.

xargs takes input, usually separated by newlines, and places them on the command line, so adding xargs makes what you had work:

find . -name .svn | xargs rm -fr

xargs is intelligent enough that it will only pass as many arguments to rm as it can accept. Thus, if you had a million files, it might run rm 1,000,000/65,000 times (if your shell could accept 65,002 arguments on the command line {65k files + 1 for rm + 1 for -fr}).

As persons have adeptly pointed out, the following also work:

find . -name .svn -exec rm -rf {} \;
find . -depth -name .svn -exec rm -fr {} \;
find . -type d -name .svn -print0|xargs -0 rm -rf

The first two -exec forms both call rm for each folder being deleted, so if you had 1,000,000 folders, rm would be invoked 1,000,000 times. This is certainly less than ideal. Newer implementations of rm allow you to conclude the command with a + indicating that rm will accept as many arguments as possible:

find . -name .svn -exec rm -rf {} +

The last find/xargs version uses print0, which makes find generate output that uses \0 as a terminator rather than a newline. Since POSIX systems allow any character but \0 in the filename, this is truly the safest way to make sure that the arguments are correctly passed to rm or the application being executed.

In addition, there's a -execdir that will execute rm from the directory in which the file was found, rather than at the base directory and a -depth that will start depth first.

Kaleb Pederson
  • 45,767
  • 19
  • 102
  • 147
31

No need for pipes, xargs, exec, or anything:

find . -name .svn -delete

Edit: Just kidding, evidently -delete calls unlinkat() under the hood, so it behaves like unlink or rmdir and will refuse to operate on directories containing files.

A B
  • 8,340
  • 2
  • 31
  • 35
  • 54
    One problem, `-delete` won't touch a directory if it contains files. – Xeoncross Jul 27 '12 at 14:50
  • 2
    There's no `-force` or recursive flag for `-delete` predicate, so this answer is useless. Thus, it's back to `|xargs rm -rf`, which is less ugly to type then `-exec` with its ugly placeholders and semicolon: `-exec rm -rf '{}' \;`. – Tomasz Gandor May 02 '14 at 13:06
14

There are already many answers provided for deleting the .svn-directory. But I want to add, that you can avoid these directories from the beginning, if you do an export instead of a checkout:

svn export <url>
Mnementh
  • 50,487
  • 48
  • 148
  • 202
  • +1, there's no need to redo this when it's already built-in to svn. – Powerlord Aug 18 '09 at 16:13
  • 1
    Only issue I see with this approach is if you want to retain unversioned files in the export. From the svn docs, "All local changes will be preserved, but files not under version control will not be copied." – raidfive Nov 10 '10 at 00:52
  • @raidfive: Usually I prefer to have all relevant files under version-control, even used libraries, so that the project works out of the box. Unversioned files in this setup are compiled binaries, that are remade by a goal in the buildfile. But you are right, if your project relies on files not under version control, an export wouldn't work. – Mnementh Nov 12 '10 at 10:26
  • but...I needed a more generalistic answer. The .svn was just the most common example, I noted that in the question. – Itay Moav -Malimovka Jul 03 '12 at 09:53
12

If you don't like to see a lot of

find: `./.svn': No such file or directory

warnings, then use the -depth switch:

find . -depth -name .svn -exec rm -fr {} \;
Miki Tebeka
  • 13,428
  • 4
  • 37
  • 49
11

In Windows, you can use the following registry script to add "Delete SVN Folders" to your right click context menu. Run it on any directory containing those pesky files.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN]
@="Delete SVN Folders"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN\command]
@="cmd.exe /c \"TITLE Removing SVN Folders in %1 && COLOR 9A && FOR /r \"%1\" %%f IN (.svn) DO RD /s /q \"%%f\" \""
Nathan Taylor
  • 24,423
  • 19
  • 99
  • 156
9

You almost had it. If you want to pass the output of a command as parameters to another one, you'll need to use xargs. Adding -print0 makes sure the script can handle paths with whitespace:

find . -type d -name .svn -print0|xargs -0 rm -rf
soulmerge
  • 73,842
  • 19
  • 118
  • 155
4
find . -name .svn |xargs rm -rf
Itay Moav -Malimovka
  • 52,579
  • 61
  • 190
  • 278
4

As an important issue, when you want to utilize shell to delete .svn folders You need -depth argument to prevent find command entering the directory that was just deleted and showing error messages like e.g.

"find: ./.svn: No such file or directory"

As a result, You can use find command like below:

cd [dir_to_delete_svn_folders]
find . -depth -name .svn -exec rm -fr {} \;
fatihk
  • 7,789
  • 1
  • 26
  • 48
3

Try this:

find . -name .svn -exec rm -v {} \;

Read more about the find command at developerWorks.

Edward Dale
  • 29,597
  • 13
  • 90
  • 129
2

Alternatively, if you want to export a copy without modifying the working copy, you can use rsync:

rsync -a --exclude .svn path/to/working/copy path/to/export
pimlottc
  • 3,066
  • 2
  • 29
  • 24