How to move and recreate a folder at the same time?

I have a folder called statistics in an Ubuntu server in which data files are regularly stored. How can I rename statistics folder to backup-xx while re-creating statistics folder to be available for storing new files?

The files in statistics folder is created by PHP file_put_contents.

I prefer renaming the folder, as there are many files in the statistics folder.

Asked By: Googlebot

mv statistics backup-xx && mkdir statistics

This would rename the existing statistics directory to backup-xx, and if that succeeds it would carry on to create a new statistics directory.

For a more atomic operation, consider creating a directory statistics-001 (or similar, maybe by replacing 001 with today’s date in a suitable format), and a symbolic link to it called statistics:

mkdir statistics-001
ln -s statistics-001 statistics

When you want to “rotate” this so that new data goes into a clean directory, create the directory first, then recreate the statistics link to it:

mkdir statistics-002
ln -sf statistics-002 statistics

mv statistics-001 backup-001

This way, any program writing to the statistics directory (i.e. the directory that this symbolic link points to) will never1 fail to find it.

If you need special permissions or ownership set on the directory that statistics points to, set these before (re-)creating the link.

1Or rather, this way, the time that a program would be without a valid target directory is minimized as much as practically possible using standard Unix tools.

Answered By: Kusalananda

There’s no way to atomically replace a directory by another directory. You can move the old directory then create a new directory:

mv statistics backup-xx
mkdir statistics

But this leaves a small window of time during which statistics doesn’t exist. This is a problem if some process may drop files in the directory at any time.

To effectively atomically replace a directory, you need to use symbolic links. Create a directory whose name includes the time period from the start:

mkdir "statistics-$(date +%Y%m%d)"

(or however you want to choose the directory naming convention). Create a symbolic link with a fixed name to the current location:

ln -s … statistics

To replace the directory, first create a new directory and a new symbolic link, and then move it to overwrite the old symbolic link. Note that neither a plain mv on the symbolic link nor a plain ln -s will do this: they would create an entry inside the target directory. GNU coreutils’s ln -snf isn’t suitable either because it removes the existing symlink before creating a new one, which leaves a small time window during which the path doesn’t exist. You can use GNU coreutils’s mv -T on the new symbolic link.

new_dir="statistics-$(date +%Y%m%d)"
mkdir "$new_dir"
ln -s
mv -Tf statistics

You can move the contents of the statistics folder to a newly created directory rather than moving folder itself. If you move entire folder then you would have to run another command to change the directory permissions.

mkdir -p <path>/backup-xxx
mv statistics/* <path>/backup-xxx/.
Answered By: Kiran Kumar Annam

Don’t rename the directory at all. You said that you prefer renaming the directory because it has a lot of files. The only reason I can think of that you would want this is because copying the files would take too long. However, moving (i.e. renaming) the files is instantaneous as long as they are moved to a location on the same file system. I assume this is what you ant to do since if you’re changing file systems, mv will take as much time as cp no matter whether it is moving a directory or its contents.

So, just do:

mkdir backup-xx && mv statistics/* backup-xx

If you need to also get hidden files, you can do:

mkdir backup-xx && mv statistics/* statistics/.* backup-xx

Or, if using bash:

shopt -s dotglob; mkdir backup-xx && mv statistics/* statistics/.* backup-xx

This way, the directory is always there but you still move its contents in a simple and fast operation.

Answered By: terdon
Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.