<p>I've played with CVS a little bit and am not the most familiar with all of its capabilities, but a huge annoyance for me is trying to add new directories that contain more directories in them. Running "<code>cvs add</code>" only adds the contents of the current directory, and using "<code>cvs import</code>" didn't look like the right thing either since it's still all code I'm producing (this howto claimed import is for <a href="http://www.thathost.com/wincvs-howto/cvsdoc/cvs_16.html#SEC136" rel="noreferrer">3rd party sources</a>)</p>

<p>Do you guys know any way to recursively add everything in a given directory to the current CVS project (or if SVN or git makes this notably easier)?</p>

[{'answer_id': 5076, 'author': 'GateKiller', 'author_id': 383, 'author_profile': 'https://Stackoverflow.com/users/383', 'pm_score': -1, 'selected': False, 'text': '<p>SVN definitely makes this trivial task, using a GUI like Tortoise is even easier, however.</p>\n\n<p>This might be a good place to start: <a href="http://www-mrsrl.stanford.edu/~brian/cvstutorial/" rel="nofollow noreferrer">http://www-mrsrl.stanford.edu/~brian/cvstutorial/</a></p>\n'}, {'answer_id': 5106, 'author': 'Mark Harrison', 'author_id': 116, 'author_profile': 'https://Stackoverflow.com/users/116', 'pm_score': 1, 'selected': False, 'text': '<p>I think this is what I did back in my CVS days:</p>\n\n<pre><code>find . -type f | xargs cvs add\n</code></pre>\n'}, {'answer_id': 5262, 'author': 'Mark Harrison', 'author_id': 116, 'author_profile': 'https://Stackoverflow.com/users/116', 'pm_score': 5, 'selected': True, 'text': '<p>Ah, spaces.  This will work with spaces:</p>\n\n<pre><code>find . -type f -print0| xargs -0 cvs add\n</code></pre>\n'}, {'answer_id': 5330, 'author': 'Chris Bunch', 'author_id': 422, 'author_profile': 'https://Stackoverflow.com/users/422', 'pm_score': 0, 'selected': False, 'text': '<p><a href="https://stackoverflow.com/a/5262/1287812">Mark\'s solution</a> resolves the spaces issue, but produces this issue:</p>\n\n<blockquote>\n  <p>cvs add: cannot open CVS/Entries for\n  reading: No such file or directory <br /> cvs\n  [add aborted]: no repository </p>\n</blockquote>\n\n<p>To fix it, the actual command to use is:</p>\n\n<pre><code>find . -type f -exec cvs add {} \\;\n</code></pre>\n'}, {'answer_id': 34893, 'author': 'John Meagher', 'author_id': 3535, 'author_profile': 'https://Stackoverflow.com/users/3535', 'pm_score': 1, 'selected': False, 'text': '<p>First add all directories to CVS</p>\n\n<pre><code>find . -type d -print0| xargs -0 cvs add\n</code></pre>\n\n<p>Then add all the files in the directories to CVS</p>\n\n<pre><code>find . -type f -print0| xargs -0 cvs add\n</code></pre>\n'}, {'answer_id': 35344, 'author': 'Alexander L. Belikoff', 'author_id': 3514, 'author_profile': 'https://Stackoverflow.com/users/3514', 'pm_score': 2, 'selected': False, 'text': '<p><code>cvs import</code> is not just for 3rd-party sources. In fact, directories are not versioned by CVS, so they are not a subject to branch policies. As long as you import empty directories, it is fine.</p>\n'}, {'answer_id': 268246, 'author': 'Oliver Giesen', 'author_id': 9784, 'author_profile': 'https://Stackoverflow.com/users/9784', 'pm_score': 2, 'selected': False, 'text': '<p>Note that you can only use <code>cvs add</code> on files and folders that are located inside an already checked out working copy, otherwise you will get the <a href="http://cvsgui.sourceforge.net/newfaq.htm#cvs-add_nodir" rel="nofollow noreferrer">"Cannot open CVS/Entries for reading"</a> message. A technique for creating a new "root module" using <code>cvs add</code> is explained in this WinCVS FAQ item: <a href="http://cvsgui.sourceforge.net/newfaq.htm#add_rootmodule" rel="nofollow noreferrer">http://cvsgui.sourceforge.net/newfaq.htm#add_rootmodule</a></p>\n\n<p>If you are on Windows, both TortoiseCVS and WinCVS support recursive addition (and optional commit) of multiple files in a single operation. In WinCvs look for the macro Add>Recursive Add (auto-commit)... In Tortoise use the Add Contents command on a directory. Both will allow you to select which files to add and what keyword expansion modes to use for them (mostly used for defining which files are binary).</p>\n\n<p>For further info about recursive add in WinCvs look here: <a href="http://cvsgui.sourceforge.net/newfaq.htm#cvs-add_recursive" rel="nofollow noreferrer">http://cvsgui.sourceforge.net/newfaq.htm#cvs-add_recursive</a></p>\n\n<hr>\n\n<p>Apart from that <code>cvs import</code> is well suited for mass-additions. However, the way <code>cvs import</code> is implemented in vanilla CVS has two drawbacks (because it <strong>was</strong> originally written for third-party code):</p>\n\n<ul>\n<li>it creates a mandatory branch with special semantics.</li>\n<li>it does not create the repository meta-data (i.e. the hidden CVS directories) needed to establish the imported code as a checked out working copy, which means that in order to actually work with the imported files you first have to check them out of the repository</li>\n</ul>\n\n<p>If you are using CVSNT you can avoid both drawbacks by specifying the <code>-nC</code> option on import. <code>-n</code> is for avoiding the "vendor" branch and <code>-C</code> is for creating the CVS directories.</p>\n'}, {'answer_id': 1979749, 'author': 'doj', 'author_id': 240829, 'author_profile': 'https://Stackoverflow.com/users/240829', 'pm_score': 1, 'selected': False, 'text': '<p>I\'m using this simple shell script, which should be started from an already checked-out CVS directory. It will stupidly try to add/commit any files and directories it finds upon its recursive search, so in the end you should end up with a fully commit tree.</p>\n\n<p>Simply save this as something like <code>/usr/bin/cvsadd</code> and don\'t forget to <code>chmod +x /usr/bin/cvsadd</code>.</p>\n\n<pre>\n#!/bin/sh\n# @(#) add files and directories recursively to the current CVS directory\n# (c) 2009 by Dirk Jagdmann \n\nif [ -z "$1" ] ; then\n    echo "usage: cvsadd \'import message\'"\n    exit 1\nfi\n\nif [ -d "$2" ] ; then\n    cvs add "$2"\n    cd "$2" || exit 1\nfi\n\nif [ ! -d CVS ] ; then\n    echo "current directory needs to contain a CVS/ directory"\n    exit 1\nfi\n\nXARGS="xargs -0 -r -t -L 1"\n\n# first add all files in current directory\nfind . -maxdepth 1 -type f -print0 | $XARGS cvs add\nfind . -maxdepth 1 -type f -print0 | $XARGS cvs ci -m "$1"\n\n# then add all directories\nfind . -maxdepth 1 -type d -not -name CVS -a -not -name . -print0 | $XARGS "$0" "$1"\n</pre>\n'}, {'answer_id': 3862101, 'author': 'phoneynk', 'author_id': 466601, 'author_profile': 'https://Stackoverflow.com/users/466601', 'pm_score': 3, 'selected': False, 'text': '<p>First add all directories to CVS</p>\n\n<pre><code>find . -type d -print0| xargs -0 cvs add\n</code></pre>\n\n<p>Then add all the files in the directories to CVS</p>\n\n<pre><code>find . -type f | grep -v CVS | xargs cvs add\n</code></pre>\n\n<p>Worked for me</p>\n'}, {'answer_id': 5158092, 'author': 'Tom', 'author_id': 639814, 'author_profile': 'https://Stackoverflow.com/users/639814', 'pm_score': 6, 'selected': False, 'text': '<p>I found this worked pretty effectively:</p>\n\n<p>First, add all the directories, but not any named "CVS":</p>\n\n<pre><code>find . -type d \\! -name CVS -exec cvs add \'{}\' \\;\n</code></pre>\n\n<p>Then add all the files, excluding anything in a CVS directory:</p>\n\n<pre><code>find . \\( -type d -name CVS -prune \\) -o \\( -type f -exec cvs add \'{}\' \\; \\)\n</code></pre>\n\n<p>Now, if anyone has a cure for the embarrassment of using CVS in this day and age...</p>\n'}, {'answer_id': 17720754, 'author': 'borrel', 'author_id': 423777, 'author_profile': 'https://Stackoverflow.com/users/423777', 'pm_score': 0, 'selected': False, 'text': '<p>i like to do (as directory\'s need an add to) </p>\n\n<pre><code>cvs status 2&gt;/dev/null | awk \'{if ($1=="?")system("cvs add "$2)}\'\n</code></pre>\n\n<p>you might need to run this multiple times(first for directory\'s then for its children) until there is no output</p>\n'}, {'answer_id': 24548144, 'author': 'Broomerr', 'author_id': 2075608, 'author_profile': 'https://Stackoverflow.com/users/2075608', 'pm_score': 1, 'selected': False, 'text': "<p>Already discussed methods will do recursive lookup, but it will fail if you perform same action again (if you want to add subtree to existed tree)\nFor that reason you need to check that your directories was not added yet and then add only files which not added yet. To do that we use output of <code>cvs up</code> to see which elements was not added yet - its will have question mark at start of line.</p>\n\n<p>We use options <code>-0</code>, <code>-print0</code> and  <code>-zZ</code> to be sure that we correctly process spaces in filenames. We also using <code>--no-run-if-empty</code> to avoid run if nothing need to be added.</p>\n\n<pre><code>CVS_PATTERN=/tmp/cvs_pattern\ncvs -z3 -q up | egrep '^\\?.*' | sed -e 's/^? //' &gt; $CVS_PATTERN\nfind . -type d \\! -name CVS -print0 | grep -zZf $CVS_PATTERN | xargs -0 --no-run-if-empty cvs add\nfind . \\( -type d  -name CVS -prune \\) -o \\( -type f  -print0 \\) | grep -zZf $CVS_PATTERN | xargs -0 --no-run-if-empty cvs add\ncvs commit -m 'commiting tree recursively'\n</code></pre>\n\n<p>With this approach we will avoid such errors:</p>\n\n<pre><code>cvs add: cannot add special file `.'; skipping\ncvs [add aborted]: there is a version in ./dirname1 already\n</code></pre>\n\n<p>and</p>\n\n<pre><code>cvs add: `./dirname2/filename' already exists, with version number 1.1.1.1\n</code></pre>\n"}, {'answer_id': 24798342, 'author': 'manufosela', 'author_id': 1833198, 'author_profile': 'https://Stackoverflow.com/users/1833198', 'pm_score': 4, 'selected': False, 'text': '<p>I use this:</p>\n\n<p>First add recursively all directories less the CVS ones:</p>\n\n<pre><code>$> find . -type d \\! -name CVS -exec cvs add \'{}\' \\;</code></pre>\n\n<p>Second add all files, less ones the CVS directories:</p>\n\n<pre> find . \\( -type d -name CVS -prune \\) -o \\( -type f -exec cvs add \'{}\' \\; \\)</pre>\n\n<p>Third do “commit” recursively like "first version" comment:</p>\n\n<pre> find . \\( -type d -name CVS -prune \\) -o \\( -type f -exec cvs commit -m "first version" \'{}\' \\; \\)</pre>\n\n<p>Last tagging all recursively:</p>\n\n<pre> find . \\( -type d -name CVS -prune \\) -o \\( -type f -exec cvs tag -F MY_CVS_TAG \'{}\' \\; \\)</pre>\n'}, {'answer_id': 37675508, 'author': 'TGA', 'author_id': 4862672, 'author_profile': 'https://Stackoverflow.com/users/4862672', 'pm_score': 2, 'selected': False, 'text': '<p>This answer from Mark was usefull (find . -type f -print0| xargs -0 cvs add) but I solved some problem that occured when the cvs add try to add his own files like Tag, Entries, ect..</p>\n\n<ol>\n<li>Add your most high level folder called NEW_FOLDER</li>\n</ol>\n\n<pre>cvs add NEW_FOLDER</pre>\n\n<ol start="2">\n<li>Use the previous command with some exclusion to add all sub-folders tree</li>\n</ol>\n\n<blockquote>\n  <p>find NEW_FOLDER/ -type d ! -name "CVS" -and ! -name "Tag" -and ! -name "Entries.Log" -and ! -name "Entries" -and ! -name "Repository" -and ! -name "Root" -print0 | xargs -0 cvs add</p>\n</blockquote>\n\n<ol start="3">\n<li>Use the previous command with some exclusion to add all files</li>\n</ol>\n\n<blockquote>\n  <p>find NEW_FOLDER/ -type f ! -name "CVS" -and ! -name "Tag" -and ! -name "Entries.Log" -and ! -name "Entries" -and ! -name "Repository" -and ! -name "Root" -print0 | xargs -0 cvs add</p>\n</blockquote>\n'}]
['https://Stackoverflow.com/questions/5071', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/422/']