解決済み:コメントの更新をご覧ください。
ファイル名に日付を含むファイルをその日付に基づいてフォルダーにソートしようとしています。これらのファイルは、次のようにファイル名にスペースがありました。古いファイルもあり、整理する必要があります。
スケジュール Fax_20180521121901.pdf
現在私たちが受け取っているファイル名にはスペースがないので、Dispatch_20180521124202.pdfです。
日付は20180521で、残りはメッセージIDのようですが、必要ありません。日付のみです。
bashスクリプト(ubuntu 18.04ボックス)を使用したこの試みは、最終的にファイルがあるディレクトリより1レベル上の2018-05-21というフォルダを作成し、すべてのPDFファイルをこのフォルダに保存しました。
for x in /home/tb/temp/*.pdf
do
d=$(date -r "$x" +%Y-%m-%d)
mkdir -p "$d"
mv -- "$x" "$d/"
done
とにかく、これは「e」というフォルダにありました。
for x in /home/tb/temp/*.pdf
do
d="${x:4:4}-${x:8:2}-${x:10:2}"
mkdir -p "$d"
mv -- "$x" "$d/"
done
この試みは?最後に、各PDFのフォルダを作成しました。
/home/tb/20180521124202.pdf/Dispatch Fax_20180521124202.pdf /home/tb/20180521121901.pdf/Dispatch Fax_20180521121901.pdf
for x in /home/tb/temp/*.pdf
do
d=$(echo "$x" | awk -F _ '{print $2}')
mkdir -p "$d"
mv -- "$x" "$d/"
done
前の投稿のスクリプトここそしてこここれらは彼らに効果がありましたが、目標は同じでしたが、私には同じ幸運はありませんでした。
私の目標は、最終的にrsyncで一時ディレクトリを入力し(別のサーバーからこのファイルをインポートする)、cronを介してこのスクリプトを実行して日付に基づいてコンテンツをフォルダに移動し、ディレクトリを有効にした「オプション+インデックス」を使用してApacheを通じて提供することです。 。このページはイントラネット専用ページであり、この特定のコンピュータから外部からアクセスすることはできません。ディレクトリ構造は簡単です。最終結果は、YYYY/MM/DD 形式に従う /var/www/html/2018/5/21 などと似ています。
私はそれがどのように機能するのかわからず、bashスクリプトの知識が非常に錆びていました。私は次のようないくつかの異なる例を見ました。これところで、ファイル名に空白があるファイルでは動作しないことがわかりました。
私はアイデアに開いています!
答え1
あなたの質問は私に完全にはっきりしていませんが、私の考えでは可能やりたいことを理解してください。
これはあなたが使用しているループです:
for x in /home/tb/temp/*.pdf
do
d="${x:4:4}-${x:8:2}-${x:10:2}"
mkdir -p "$d"
mv -- "$x" "$d/"
done
あなたが提供したサンプルファイル名は次のとおりです。
Dispatch Fax_20180521121901.pdf
Dispatch_20180521124202.pdf
私にとって顕著な問題の1つは、パラメータ置換式(d="${x:4:4}-${x:8:2}-${x:10:2}"
)が正しい結果を生成していないようです。たとえば、次のようになります。
> x='Dispatch Fax_20180521121901.pdf'
> d="${x:4:4}-${x:8:2}-${x:10:2}"
> echo ${d}
atch- F-ax
> x='Dispatch_20180521124202.pdf'
> d="${x:4:4}-${x:8:2}-${x:10:2}"
> echo ${d}
atch-_2-01
grep
代わりに、次のように試すことができます。
> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | grep -Po '\d{8}')
> echo ${d}
20180521
> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | grep -Po '\d{8}')
> echo ${d}
20180521
または、ハイフンを追加する場合は、次のsed
コマンドベースの置換を使用できます。
> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | sed -E 's/^[^0-9]*([0-9]{4})([0-9]{2})([0-9]{2}).*$/\1-\2-\3/')
> echo ${d}
2018-05-21
> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | sed -E 's/^[^0-9]*([0-9]{4})([0-9]{2})([0-9]{2}).*$/\1-\2-\3/')
> echo ${d}
2018-05-21
これが目的の結果であると仮定すると(型のサブディレクトリが必要な場合など%Y-%m-%d
)、パラメータ置換式をベースのコマンド置換にgrep
置き換えることができます。これにより、次のような修正されたループが提供されます。
for filename in /home/tb/temp/*.pdf; do
datestring=$(echo "${filename}" | sed -E 's/^[^0-9]*([0-9]{4})([0-9]{2})([0-9]{2}).*$/\1-\2-\3/')
mkdir -p "${datestring}"
mv -i -- "${filename}" "${datestring}/"
done
これにより、フォームのサブディレクトリが作成され、%Y-%m-%d
適切なファイルで埋められます。
修正する:あなたの意見によると、あなたが望むものはフォームの入れ子になったサブディレクトリのようです%Y/%m/%d
。これを行うには、年、月、日の文字列を別々に抽出する必要があります。たとえば、次のようになります。
> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | grep -Po '\d{8}')
> year=${d:0:4}
> month=${d:4:2}
> day=${d:6:2}
> echo "${year}/${month}/${day}/"
2018/05/21/
これにより、次のループが発生します。
for filename in /home/tb/temp/*.pdf; do
datestring=$(echo "${filename}" | grep -Po '\d{8}')
year=${datestring:0:4}
month=${datestring:4:2}
day=${datestring:6:2}
directory="${year}/${month}/${day}/"
mkdir -p "${directory}"
mv -i -- "${filename}" "${directory}"
done
答え2
積極的に敵対的なファイル名を処理する必要がない場合は、
sed -E 's/([0-9]{0,7}[^0-9]+)*([0-9]{8}).*/mkdir -p \2; mv "&" \2/e'
# 111111111111111111 2222222222
パターンは0〜7桁の数字で、その後には数字ではなく数字が数回出て、その後に8桁の数字が1回出てきます。 2番目のパターンは日付と一致する8桁の数字です。
GNU sedがない場合は、e
結果をフラグの代わりにシェルにパイプできます。