Copiar arquivos baseados em datas no nome do arquivo

1

Estou tendo um problema ao tentar copiar arquivos de intervalo de um diretório para outro com base em uma data contida no nome do arquivo. A data no nome do arquivo é em UTC, enquanto as datas criadas são em CST. Todos os nomes de arquivos contidos no diretório possuem nomes de arquivos semelhantes a este:

foo_20160227_0015.gif
foo_20160227_0030.gif
.....
.....
foo_20160304_0030.gif
foo_20160304_0045.gif

O script que estou tentando usar é o seguinte:

# Variables
strPrevDay=$(date +"%Y%m%d" -d "yesterday")
str7DaysAgo=$(date +"%Y%m%d" -d "7 days ago")
strImgDir="~/Documents/Projects/Radar/Images/"
strTmpImgDir="~/Documents/Projects/Radar/Images/Temp/"
strFileName="foo_"
strFile=

# Copy files created in the last week
for f in $strImgDir$strFileName{$str7DaysAgo..$strPrevDay}*.gif; do cp "$f" $strTmpImgDir; done

Em seguida, recebo a seguinte mensagem de erro quando o script é executado:

cp: cannot stat ‘/home/user/Documents/Projects/Radar/Images/foo_{20160227..20160304}*.gif’: No such file or directory
    
por Mr Xaero 06.03.2016 / 02:38

2 respostas

2

O motivo desse erro é que {$str7DaysAgo..$strPrevDay} expande as chaves primeiro (o que não faz nada, pois não está no formato {NUMBER1..NUMBER2} ) e, em seguida, expande as variáveis. É uma armadilha.

Por 7 dias, não é irracional enumerar os dias com date . Veja a resposta de Jeff Schaller .

Outra opção é usar eval para forçar as avaliações a acontecerem na ordem desejada. Usar eval é propenso a erros, já que você precisa ter muito cuidado com as partes que são avaliadas duas vezes, mas aqui temos partes de nomes de arquivos que são conhecidos por conter apenas dígitos, portanto, tudo bem. Observe que você precisará ativar a opção nullglob no caso há dias em que nenhum arquivo é produzido.

#!/bin/bash
last_day=$(date +"%Y%m%d" -d "yesterday")
first_day=$(date +"%Y%m%d" -d "7 days ago")
eval "all_days=({$first_day..$last_day})"
image_directory=~/Documents/Projects/Radar/Images/
temporary_directory="$image_directory/Temp/"
filename_prefix="foo_"
shopt -s nullglob
for day in "${all_days[@]}"; do
  files=("$image_directory/$filename_prefix$day"*.gif)
  if [[ ${#files[@]} != 0 ]]; then
    cp "${files[@]}" "$temporary_directory"
  fi
done

(Eu também consertei suas citações - e seus nomes de variáveis difíceis de ler. Observe que VAR="~/something" coloca um til em VAR , você precisa deixar o til sem aspas para obter o diretório inicial. Bash então expande o til porque você tinha uma expansão de variável sem aspas, que quebraria se os nomes dos diretórios contivessem espaços em branco ou outros caracteres especiais de shell - não deixe as variáveis sem aspas, a menos que você saiba que é necessário.

Uma abordagem alternativa é enumerar os arquivos e copiar apenas os que estão no intervalo desejado. É provável que seja mais rápido para grandes intervalos, porque cada uso de um caractere curinga deve enumerar os arquivos no diretório (não há uma maneira mais rápida de obter os arquivos correspondentes a um padrão específico).

#!/bin/bash
last_day=$(date +"%Y%m%d" -d "yesterday")
first_day=$(date +"%Y%m%d" -d "7 days ago")
image_directory=~/Documents/Projects/Radar/Images/
temporary_directory="$image_directory/Temp/"
filename_prefix="foo_"
shopt -s nullglob
for file in "$image_directory/$filename_prefix"*.gif; do
  file_date="${file##*/"$filename_prefix"}"; file_date=${file_date:0:8}
  if ((file_date >= first_day && file_date <= last_day)); then
    cp "$file" "$temporary_directory"
  fi
done
    
por 06.03.2016 / 21:59
1

Já que você parece ter a data do GNU, aqui está uma solução simplista:

#!/usr/bin/env bash
str7DaysAgo=$(date +"%Y%m%d" -d "7 days ago")
str6DaysAgo=$(date +"%Y%m%d" -d "6 days ago")
str5DaysAgo=$(date +"%Y%m%d" -d "5 days ago")
str4DaysAgo=$(date +"%Y%m%d" -d "4 days ago")
str3DaysAgo=$(date +"%Y%m%d" -d "3 days ago")
str2DaysAgo=$(date +"%Y%m%d" -d "2 days ago")
str1DaysAgo=$(date +"%Y%m%d" -d "1 days ago")
strImgDir="~/Documents/Projects/Radar/Images/"
strTmpImgDir="~/Documents/Projects/Radar/Images/Temp/"
strFileName="foo_"
base="${strImgDir}${strFileName}"

# Copy files created in the last week
for f in ${strImgDir}/*.gif
do 
  if [[ "$f" =~ ${strFileName}${str7DaysAgo} || \
        "$f" =~ ${strFileName}${str6DaysAgo} || \
        "$f" =~ ${strFileName}${str5DaysAgo} || \
        "$f" =~ ${strFileName}${str4DaysAgo} || \
        "$f" =~ ${strFileName}${str3DaysAgo} || \
        "$f" =~ ${strFileName}${str2DaysAgo} || \
        "$f" =~ ${strFileName}${str1DaysAgo} \
     ]]
       cp "$f" $strTmpImgDir
  fi
done
    
por 06.03.2016 / 03:22