Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Is it possible to automatically rename a file when it's placed in a specific directory?

For example I have a directory named "dir0".I move or copy a file named "file1" to "dir0".then "file1" should rename to "file1_{current timestamp}"

share|improve this question
1  
Take a look at inotify (linux.die.net/man/7/inotify). But can't you just copy to the properly named file with added timestamp right away? –  alex Jul 4 '11 at 10:28

3 Answers 3

up vote 19 down vote accepted

Usually you would do this programatically at the time you create or move the file, but it is possible to trigger a script whenever a file gets created or moved to a folder using incron. Set up your tab file using incrontab -e with a line like this, but with your paths of course:

/path/to/dir0 IN_MOVED_TO,IN_CREATE /path/to/script $@/$#

Then in /path/to/script write a quick rename action. Be aware that the script will also get called for the new file that you create, so it has to test whether the file has been appropriately named already or not. In this example it checks to see if the file has a ten-digit number for seconds from epoch as the last part of the file name, and if it doesn't, it adds it:

#!/bin/bash
echo $1 | grep -qx '.*_[0-9]\{10\}' || mv "$1" "$1_$(date +%s)"

Edit: When I first wrote this up I was short on time and couldn't figure out how to make bash do the pattern matching here. Gilles pointed out how to do this without invoking grep using ERE matching in bash:

#!/bin/bash
[[ ! ( $1 =~ _[0-9]{10}$ ) ]] && mv "$1" "$1_$(date +%s)"
share|improve this answer

I think that inotify is tool that coul be used in this case. In Debian there is tool inoticoming for executing action on file creation:

 inoticoming --foreground /path/to/directory mv {} {}-"`date`" \;

{} will be replaced with the filename.

The command that I provided isn't complete - it cause a loop because when the file will be renamed it will be recognized as new so it will get mved AGAIN and so on. To avoid this you could use --suffix option if you know what suffix will be in file before rename.

share|improve this answer
    
@Caleb: thanks for correcting me... –  pbm Jul 4 '11 at 15:04
    
No problem. I've never heard of inoticoming. Out of curiosity, when would it be better to use this over inocron? –  Caleb Jul 4 '11 at 15:31
    
I don't know if it is better. I heard about it some time ago, but I never tried it... Now I found opinion that inoticoming is "similar to incrond, but lighter weight and not started as a default daemon", so I think it's just another solution with slighly different approach... I think that incron is more popular - I have little trouble to find inoticoming home page an package for it outside Debian... –  pbm Jul 4 '11 at 15:45
    
I think you just posted the wrong link. My distro doesn't seem to have it anywhere. –  Caleb Jul 4 '11 at 15:51
    
I found inoticoming only in Debian based distributions (in my Gentoo there is no ebuild for it). On page that I posted there are two packages: reprepro and below it inoticoming... –  pbm Jul 4 '11 at 15:57

You could just take a script like this and have it running... I'll leave it as an exercise for the reader to add the extra bits to have it start as a service and prevent multiple copies running at once.

#!/usr/bin/perl
use strict;
use warnings;
use File::Slurp;
use POSIX qw(strftime);

chdir($ENV{STAMP_DIR} || '/home/me/dir0')
    or die "Cannot get to stamp dir: $!\n";

while (1) {
    my $stamp = strftime("_%Y%m%d%H%M%S", localtime);
    for my $orig ( grep { $_ !~ /_\d{14}$/ } read_dir('.') ) {
        rename $orig, "$orig$stamp"
            or warn "Failed to rename $orig to $orig$stamp: $!\n";
    }
    sleep($ENV{STAMP_DELAY} || 10);
}

And here's it working:

$ STAMP_DIR=/home/me/stamps STAMP_DELAY=1 ./t.pl &
[1] 6989
$ cd stamps/
$ ls
$ touch hello
$ ls
hello_20110704033253
$ touch world
$ ls
hello_20110704033253
world_20110704033258
$ touch hello
$ ls
hello_20110704033253
hello_20110704033302
world_20110704033258
share|improve this answer
    
Of course perl can do anything, but a persistent script that runs on a X-second while-true loop is definitely a hack when you can get event notifications about file-writes and respond instantly without wasting resources the rest of the time. –  Caleb Jul 4 '11 at 15:04
    
@Caleb - Very true. Just giving possibilities. Of course, if you're doing it via system notification, you have the possibility of getting two file creates with the same name within the same second, so the attached scripts should handle those circumstances. –  Mark Mann Jul 4 '11 at 19:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.