cp -p foo.txt foo.txt.'date +%Y.%m.%d.%H.%M.%S'
É possível executar um comando cp
que cria um backup de um arquivo e o renomeia com data / hora de hoje
por exemplo:
cp -p foo.txt foo.txt.'date -I'
isso coloca uma data no formato ISO aaaa-mm-dd
Copie o trecho de código abaixo para mkcp.c e compile com
# gcc -o mkcp mkcp.c
no linux ou # cl mkcp.c
no Windows®. # ./mkcp mkcp.c
, em seguida, executa o comando cp
e cria uma cópia como mkcp.c_sav_2018-01-04
.
#ifdef __linux__
#include<dirent.h>
#endif
#include<errno.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/stat.h> // mkdir
#include<sys/types.h>
#include<time.h>
#ifdef __linux__
#include<unistd.h>
#endif
#if defined(_MSC_VER)
#include<BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
#if defined(__TINYC__)
#include "./dirent.h"
typedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */
struct DIR
{
handle_type handle; /* -1 for failed rewind */
struct _finddata_t info;
struct dirent result; /* d_name null iff first time */
char *name; /* null-terminated char string */
};
DIR *opendir(const char *name)
{
DIR *dir = 0;
if(name && name[0])
{
size_t base_length = strlen(name);
const char *all = /* search pattern must end with suitable wildcard */
strchr("/\", name[base_length - 1]) ? "*" : "/*";
if((dir = (DIR *) malloc(sizeof *dir)) != 0 &&
(dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0)
{
strcat(strcpy(dir->name, name), all);
if((dir->handle =
(handle_type) _findfirst(dir->name, &dir->info)) != -1)
{
dir->result.d_name = 0;
}
else /* rollback */
{
free(dir->name);
free(dir);
dir = 0;
}
}
else /* rollback */
{
free(dir);
dir = 0;
errno = ENOMEM;
}
}
else
{
errno = EINVAL;
}
return dir;
}
int closedir(DIR *dir)
{
int result = -1;
if(dir)
{
if(dir->handle != -1)
{
result = _findclose(dir->handle);
}
free(dir->name);
free(dir);
}
if(result == -1) /* map all errors to EBADF */
{
errno = EBADF;
}
return result;
}
struct dirent *readdir(DIR *dir)
{
struct dirent *result = 0;
if(dir && dir->handle != -1)
{
if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
{
result = &dir->result;
result->d_name = dir->info.name;
}
}
else
{
errno = EBADF;
}
return result;
}
#endif
int cp(const char *from, const char *to) {
int fd_to, fd_from;
char buf[4096];
ssize_t nread;
int saved_errno;
fd_from = open(from, O_RDONLY);
if (fd_from < 0) {
fprintf(stderr,"Error opening input file %s.\n", from);
return -1;
}
fd_to = open(to, O_WRONLY | O_CREAT | O_EXCL, 0666);
if (fd_to < 0) {
fprintf(stderr,"Error opening output file %s.\n", to);
fprintf(stderr,"Most probably an output file %s exists already.\n", to);
goto out_error;
}
while (nread = read(fd_from, buf, sizeof buf), nread > 0) {
char *out_ptr = buf;
ssize_t nwritten;
do {
nwritten = write(fd_to, out_ptr, nread);
if (nwritten >= 0) {
nread -= nwritten;
out_ptr += nwritten;
} else if (errno != EINTR) {
goto out_error;
}
} while (nread > 0);
}
if (nread == 0) {
if (close(fd_to) < 0) {
fd_to = -1;
goto out_error;
}
close(fd_from);
/* Success! */
return 0;
}
out_error:
saved_errno = errno;
close(fd_from);
if (fd_to >= 0) close(fd_to);
errno = saved_errno;
return -1;
}
mode_t getumask() {
mode_t mask = umask(0);
umask (mask);
return mask;
}
void help(char *this_program) {
printf("usage: %s [options] fts\n", this_program);
printf("options:\n");
printf("-h,--help Show this help.\n");
printf("fts File or folder to save.\n");
}
void rmkdr(const char *dr) {
#ifdef __linux__
if (mkdir(dr,0777-getumask()) == -1) {
// perror(argv[0]);
fprintf(stderr,"Failed to create the folder %s.\n", dr);
fprintf(stderr,"Most likely a folder %s exists already.\n", dr);
fprintf(stderr,"Stop.\n");
exit(EXIT_FAILURE);
}
#endif
#if defined(__TINYC__)
if (mkdir(dr) == -1) {
// perror(argv[0]);
fprintf(stderr,"Failed to create the folder %s.\n", dr);
fprintf(stderr,"Most likely a folder %s exists already.\n", dr);
fprintf(stderr,"Stop.\n");
exit(EXIT_FAILURE);
}
#endif
}
int lmdir(const char *dr, char *ndr) {
char *oldpath;
char *newpath;
DIR *dir;
int res;
size_t newneeded, oldneeded;
struct dirent *entry;
if(!(dir = opendir(dr))) {
fprintf(stderr, "Argument is not a folder.\n");
fprintf(stderr,"Stop.\n");
exit(EXIT_FAILURE);
}
while((entry = readdir(dir)) != NULL) {
#ifdef __linux__
newneeded = snprintf(NULL, 0, "%s/%s", ndr,entry->d_name) + 1;
oldneeded = snprintf(NULL, 0, "%s/%s", dr,entry->d_name) + 1;
newpath = malloc(newneeded);
oldpath = malloc(oldneeded);
snprintf(newpath, newneeded, "%s/%s",ndr,entry->d_name);
snprintf(oldpath, oldneeded, "%s/%s",dr,entry->d_name);
if(entry->d_type == DT_DIR) {
if(strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0) continue;
rmkdr(newpath);
lmdir(oldpath, newpath);
} else if(entry->d_type == DT_REG) {
res=cp(oldpath,newpath);
free(newpath);
free(oldpath);
if(res!=0) {
exit(EXIT_FAILURE);
}
}
#endif
#if defined(__TINYC__)
newneeded = snprintf(NULL, 0, "%s/%s", ndr,entry->d_name) + 1;
oldneeded = snprintf(NULL, 0, "%s/%s", dr,entry->d_name) + 1;
newpath = malloc(newneeded);
oldpath = malloc(oldneeded);
snprintf(newpath, newneeded, "%s/%s",ndr,entry->d_name);
snprintf(oldpath, oldneeded, "%s/%s",dr,entry->d_name);
if(opendir(oldpath) != NULL) {
if(strcmp(entry->d_name,".") == 0 || strcmp(entry->d_name,"..") == 0) continue;
rmkdr(newpath);
lmdir(oldpath, newpath);
} else {
res=cp(oldpath,newpath);
if(res!=0) {
fprintf(stderr, "Exit failure.\n",res);
exit(EXIT_FAILURE);
}
}
#endif
free(newpath);
free(oldpath);
}
}
int main(int argc, char *argv[]) {
char *cpstr;
char *drstr;
char *dtstr;
DIR *dir;
int i, res=0;
time_t t = time(NULL);
struct dirent *dptr;
struct tm tml;
tml = *localtime(&t);
for(i=0; i<argc; i++) {
if(strcmp(argv[i],"--help")==0||strcmp(argv[i],"-h")==0) {
help(argv[0]);
return(0);
}
}
if(argc<2) {
help(argv[0]);
return(1);
}
if(argv[1][strlen(argv[1])-1]=='/') {
drstr=(char *) malloc((strlen(argv[1]))*sizeof(char));
snprintf(drstr,strlen(argv[1]),"%s",argv[1]);
} else {
drstr=(char *) malloc(1+strlen(argv[1])*sizeof(char));
snprintf(drstr,1+strlen(argv[1]),"%s",argv[1]);
}
dtstr = (char *) malloc(12*sizeof(char));
snprintf(dtstr, 11, "%d-%02d-%02d", tml.tm_year + 1900, tml.tm_mon + 1, tml.tm_mday);
cpstr = (char *) malloc((1+strlen(dtstr)+strlen(drstr)+strlen("_sav_"))*sizeof(char));
strcpy(cpstr, drstr);
strcat(cpstr, "_sav_");
strcat(cpstr, dtstr);
if(!(dir = opendir(argv[1]))) {
res=cp(argv[1],cpstr);
if(res!=0) {
fprintf(stderr,"Stop.\n");
exit(EXIT_FAILURE);
}
fprintf(stdout, "Output to be written to: %s.\n", cpstr);
fprintf(stdout, "Success.\n");
free(cpstr);
free(drstr);
free(dtstr);
exit(EXIT_SUCCESS);
}
rmkdr(cpstr);
lmdir(drstr, cpstr);
if(res==0) {
printf("Output to be written to: %s.\n", cpstr);
printf("Success.\n");
}
free(cpstr);
free(drstr);
free(dtstr);
return(0);
}
Nota: mkcp
verifica se o arquivo a ser gravado já existe. mkcp
será interrompido nesse caso. Consequentemente, qualquer risco de perda de dados é minimizado.
cp foo.txt{,'date +%Y.%m.%d.%H.%M.%S'}
cp foo{,$(date -I)}
E se o que você realmente quer é uma edição rápida usando sed, use algo como sed -i.$(date -I) -e ...
O formato de saída para date -I
é como 2018-12-31
Felicidades, Cameron