ファイル名に含まれる日付に基づいて一連のファイルをあるディレクトリから別のディレクトリにコピーしようとすると問題が発生します。ファイル名の日付は UTC 時間、生成日は CST 時間です。ディレクトリに含まれるすべてのファイル名には、次のようなファイル名があります。
foo_20160227_0015.gif
foo_20160227_0030.gif
.....
.....
foo_20160304_0030.gif
foo_20160304_0045.gif
私が使用したいスクリプトは次のとおりです。
# 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
スクリプトが実行された後、次のエラーメッセージが表示されます。
cp: cannot stat ‘/home/user/Documents/Projects/Radar/Images/foo_{20160227..20160304}*.gif’: No such file or directory
答え1
このエラーは、中{$str7DaysAgo..$strPrevDay}
かっこが最初に拡張された後(フォームではないため、何もしません)変数が拡張されるために発生します。これはバッシュトラップです。{NUMBER1..NUMBER2}
日数を計算するために7日を使用するのは無理ではありませんdate
。バラよりジェフ・シャラーの答え。
別の選択肢は、eval
評価が望ましい順序で行われるように強制することです。 2回評価される部分には非常に注意する必要があるため、使用エラーが発生しやすいが、eval
ここではファイル名部分に数字だけが含まれていることを知っているので問題にはなりません。必要な点を参考にしてくださいnullglob
このオプションをオンにしてください数日間ファイルが生成されない場合。
#!/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
VAR="~/something"
(引用符と読みにくい変数名も修正しましたVAR
。他のシェル特殊文字が含まれている場合は中断されます。
別のアプローチは、ファイルを列挙し、目的の範囲内のファイルのみをコピーすることです。ワイルドカードを使用するたびにディレクトリ内のファイルを列挙する必要があるため、範囲が大きい場合は高速になります(特定のパターンに一致するファイルを取得するより高速な方法はありません)。
#!/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
答え2
GNUの日付があるようですので、簡単な解決策は次のとおりです。
#!/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