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}"
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityIs 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}"
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)"
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 mv
ed AGAIN and so on. To avoid this you could use --suffix
option if you know what suffix will be in file before rename.
inoticoming
. Out of curiosity, when would it be better to use this over inocron
?
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...
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
...
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
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.