Renomear arquivos automaticamente 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". Movo ou copio um arquivo chamado "file1" para "dir0". Então "file1" deve renomear para "file1_ {current timestamp}"

Nick.h
fonte
1
Dê uma olhada no inotify ( linux.die.net/man/7/inotify ). Mas você não pode simplesmente copiar para o arquivo nomeado corretamente com o carimbo de data / hora adicionado imediatamente?
alex

Respostas:

21

Normalmente, você faria isso programaticamente no momento em que cria ou move o arquivo, mas é possível disparar um script sempre que um arquivo é criado ou movido para uma pasta usando incron. Configure seu arquivo de tabulação usando incrontab -euma linha como esta, mas com seus caminhos, é claro:

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

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

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

Edit: Quando eu escrevi isso, eu estava com pouco tempo e não conseguia descobrir como bashfazer o padrão correspondente aqui. Gilles apontou como fazer isso sem chamar o grep usando a correspondência ERE no bash:

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

Eu acho que inotifyé uma ferramenta que pode ser usada neste caso. No Debian, existe uma ferramenta inoticomingpara executar ações 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 - causa um loop, porque quando o arquivo for renomeado, ele será reconhecido como novo e será mveditado novamente. Para evitar isso, você pode usar a --suffixopção se você souber qual sufixo estará no arquivo antes de renomear.

pbm
fonte
Sem problemas. Eu nunca ouvi falar disso inoticoming. Por curiosidade, quando seria melhor usar isso de novo inocron?
Caleb
Não sei se é melhor. Ouvi falar disso há algum tempo, mas nunca tentei ... Agora achei uma opinião inoticoming"semelhante a incrond, mas mais leve e não iniciada como um daemon padrão", então acho que é apenas mais uma solução com uma abordagem ligeiramente diferente. .. Eu acho que isso incroné mais popular - tenho poucos problemas para encontrar um pacote para a inoticoming home page fora do Debian ... #
234
Acho que você acabou de postar o link errado. Minha distribuição não parece ter isso em lugar nenhum.
Caleb
Eu encontrei inoticomingapenas em distribuições baseadas no Debian (no meu Gentoo não há ebuild para isso). Na página que eu publiquei, existem dois pacotes: repreproe abaixo dela inoticoming... #
234
2

Você pode pegar um script como esse e colocá-lo em execução ... Vou deixar como um exercício para o leitor adicionar os bits extras para que ele comece como um serviço e impedir que várias cópias sejam executadas ao mesmo tempo.

#!/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á o trabalho:

$ 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
antitônico
fonte
É claro que perl pode fazer qualquer coisa, mas um script persistente que é executado em um loop while-true de X segundos é definitivamente um hack quando você pode receber notificações de eventos sobre gravação de arquivos e responder instantaneamente sem desperdiçar recursos o resto do tempo.
Caleb
@ Caleb - Muito verdade. Apenas dando possibilidades. Obviamente, se você estiver fazendo isso por meio da notificação do sistema, terá a possibilidade de obter duas criações de arquivos com o mesmo nome no mesmo segundo, portanto os scripts anexados devem lidar com essas circunstâncias.
Unpythonic