Shrink/reset directory size?

Solution 1:

See also rm on a directory with millions of files; tangentially related, but we discuss it there.

As far as I'm aware, at least on ext2/3, no, there's no (online) way to shrink them short of delete + recreate. Unmounted, several sources suggest e2fsck -D might work, though I can claim no personal experience with that option.

Some references for further reading:

  • http://linux.derkeiler.com/Mailing-Lists/Kernel/2009-05/threads.html#06569
  • http://fedoraforum.org/forum/showthread.php?t=120654

Solution 2:

I recently had to delete and recreate an NFS directory to shrink its size after it had previously bloated. In the process, I found a fairly efficient way to do this using rsync and hard links. This method avoids copying the actual files, while still accomplishing the goal of recreating the directory with the same contents.

Since we needed to take downtime to do this operation during our maintenance window, making the rebuilt directory available as soon as possible was important for us. If simplicity is more important to you, change the first move command to an 'rm -rf' on the source directory, and skip the other 'rm -rf' command.

I extracted these commands from a larger process, and abstracted the directory names, so apologies if I've made a mistake in that translation.

mkdir /tmp/holding_dir/
rsync -ai --delete --link-dest=/path/to/source_dir/ /path/to/source_dir/ /tmp/holding_dir/
mv /path/to/source_dir/ /tmp/deleteme/
mv /tmp/holding_dir/ /path/to/source_dir/

Then later, we remove the directory. Depending on size, you may need to use a more sophisticated technique to do this. For example, using rsync with the --delete flag to sync an empty directory into this directory may be more efficient.

rm -rf /tmp/deleteme/

Solution 3:

I'd do it like this.

cp -aloldirnewdir&& mvolddirtempname&& mvnewdirolddir&& rm -rtempname

where olddir is the directory you want to shrink newdir and tempname are temporary filenames

cp -al creates links to the content of olddir in newdir and the next three commands swap them with newdir and clean up.