Renomeia automaticamente os arquivos quando eles são colocados em um diretório específico

14

É possível renomear automaticamente um arquivo quando ele é colocado em um diretório específico?

Por exemplo, eu tenho um diretório chamado "dir0". Eu movo ou copio um arquivo chamado "file1" para "dir0". Então "file1" deve renomear para "file1_ {timestamp atual}"

    
por Nick.h 04.07.2011 / 11:43

3 respostas

21

Geralmente, você faria isso programaticamente no momento em que cria ou move o arquivo, mas é possível acionar um script sempre que um arquivo é criado ou movido para uma pasta usando incron . Configure seu arquivo de guia usando incrontab -e com uma linha como essa, mas com seus caminhos, é claro:

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

Em /path/to/script , escreva uma ação rápida de renomeação. Esteja ciente de que o script também será chamado para o novo arquivo que você criar, portanto, ele deve testar se o arquivo já foi apropriadamente chamado já ou não. Neste exemplo, ele verifica se o arquivo tem um número de dez dígitos para segundos da época como a última parte do nome do arquivo e, se não, adiciona: ep / d

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

Editar: Quando escrevi isso pela primeira vez, tive pouco tempo e não consegui descobrir como fazer bash fazer a correspondência de padrões aqui. Gilles apontou como fazer isso sem invocar o grep usando a correspondência ERE no bash:

#!/bin/bash
[[ ! ( $1 =~ _[0-9]{10}$ ) ]] && mv "$1" "$1_$(date +%s)"
    
por 04.07.2011 / 12:47
5

Acho que inotify é uma ferramenta que pode ser usada neste caso. No Debian existe a ferramenta inoticoming para executar a ação na criação de arquivos:

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

{} será substituído pelo nome do arquivo.

O comando que eu forneci não está completo - ele causa um loop porque quando o arquivo for renomeado, ele será reconhecido como novo, então ele obterá mv ed AGAIN e assim por diante. Para evitar isso, você pode usar a opção --suffix se souber qual sufixo estará no arquivo antes de renomear.

    
por 04.07.2011 / 12:53
2

Você pode simplesmente pegar um script como esse e executá-lo ... Vou deixar como um exercício para o leitor adicionar os bits extras para que ele comece como um serviço e impeça que várias cópias sejam executadas de uma só vez. / p>

#!/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);
}

E aqui está funcionando:

$ 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
    
por 04.07.2011 / 12:35