このディレクトリには約100万のファイルがあります。/home/username/images/
各ファイルの名前は次のとおりです。012345678910(Place)_0_20120414185957_28841.jpg
ファイル名のタイムスタンプ部分は各画像で変更されます。
以下のコードには、ファイルをこの日付構造にソート/移動するコードが含まれています。/home/username/sorted/2012/04/14/18/name_of_file.jpg
小さなファイルサンプルの場合はうまく機能しますが、大きなディレクトリの場合は、出力後にパテ端末の接続が切断されます。
Directory $newdir does not exist. Creating same.
常に間違ったコードが原因で終了する他のコードがありますargument list too long
。
コードは次のとおりです。
#!/bin/bash
ALLFILES=(images/*)
for ((i=0; i<${#ALLFILES[*]}; i+=30000));
do
set $(echo "${ALLFILES[@]:i:30000}" | awk -F_ '{print $1, $2, $3, $4, $5}')
fullyear=$3
year=$(echo $fullyear |cut -c1-4)
month=$(echo $fullyear |cut -c5-6)
day=$(echo $fullyear |cut -c7-8)
hour=$(echo $fullyear |cut -c9-10)
newdir=$(echo /home/username/sorted/$year/$month/$day/$hour/)
if ! [ -d $newdir ]; then
echo Directory $newdir does not exist. Creating same.
mkdir -p $newdir;
fi
mv "${ALLFILES[@]:i:30000}" $newdir;
done
大規模なループを実行しても接続が維持されない理由についてのアイデアはありますか?
答え1
スクリーンセッションで実行してみてください。または別の構造を試してみてください。私はfind + sedが純粋なbashよりもうまくいくと信じています。
find images/ -name "*.jpg" | sed 's%^[^_]*_[^_]*_\([0-9][0-9][0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\).*%mkdir -p "/home/username/sorted/\1/\2/\3/\4" \&\& mv "&" "/home/username/sorted/\1/\2/\3/\4/"%'
これは、sed makeコマンドがどのように機能するかを示すためのものです。コマンドはe
最後に以下を追加した後に%
実行されます。
find images/ -name "*.jpg" | sed 's%^[^_]*_[^_]*_\([0-9][0-9][0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9]\).*%mkdir -p "/home/username/sorted/\1/\2/\3/\4" \&\& mv "&" "/home/username/sorted/\1/\2/\3/\4/"%e'
PS:bashでは使用する必要はありません
day=$(echo $fullyear |cut -c7-8)
Bashは次のことなく自分で行うことができますecho | cut
。
day=${fullyear:6:2}
答え2
ファイルを含むディレクトリのルートにあるこのシェルスクリプトを使用して、すべてのファイルをyear/month
同様の構造に移動します。
#!/usr/bin/env bash
if [ ! $1 ]; then
echo "Usage: ./pictures.sh jpg"
exit 1
fi
for f in *."$1"; do
FILENAME="$f"
YEAR=`date -j -f "%s" $(stat -f "%m" "$FILENAME") +"%Y"`
MONTH=`date -j -f "%s" $(stat -f "%m" "$FILENAME") +"%m_%B"`
DEST="$YEAR/$MONTH"
if [ ! -d "$DEST" ]; then
mkdir -p "$DEST"
fi
echo "Moving $FILENAME to $DEST/$FILENAME ..."
mv "$FILENAME" "$DEST/$FILENAME"
done
目的:$ ./pictures.sh JPG
* .JPGを正しい構造に移動します。
答え3
また、画像を日付構造のディレクトリに配置しますが、アプローチは少し異なります。私の画像はYYYY-MM
タイムスタンプに基づいてそのディレクトリに入ることを望みます。だから私がしたことは、ls -l *.jpg > tmp.txt
画像フォルダから始めてtmp.txt
ループに入れて、各ファイルのタイムスタンプを取得することでした。タイムスタンプを取得する方法が見つかりませんでした。
これは私のコードです。
#!/bin/bash
hostdir="/home/Photos/"
destdir="/tmp/sorted"
cd $hostdir
touch /tmp/tmpsort.txt
ls -l *.jpg > /tmp/tmpsort.txt
while read line
do
filename=$(echo $line | awk '{print $8}')
filedate=$(echo $line | awk '{print $6}')
filedir=${filedate:0:7}
if [ ! -d $destdir/$filedir ]; then
mkdir -p $destdir/$filedir
fi
# Let's skip files that were already sorted from a previous run
if [ ! -f $destdir/$filedir/$fiename ]; then
cp $filename $destdir/$filedir/
fi
done < /tmp/tmpsort.txt
rm /tmp/tmpsort.txt
並べ替える画像は何百万ものありません。ソートしたら、このコードを実行するのにかなり長い時間がかかります。しかし、期待どおりに動作します。
答え4
次の行は、変更時間に応じてファイルを正しいフォルダに移動するシェルスクリプトを生成します。
find . -type f -not -name ".DS*" -exec stat -f "mkdir -p %Sm; mv \"%N\" %Sm" -t "%Y/%m/%d" {} \; > move.sh
sh move.sh
.DS* ファイルを除外しました (-not -name ".DS*")。 move.shを実行する前に編集して、不要なファイルを削除できます。