將大量檔案移至日期結構化目錄順序

將大量檔案移至日期結構化目錄順序

我在這個目錄中有大約 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'

附:你不需要在 bash 中使用

day=$(echo $fullyear |cut -c7-8)

Bash 可以自行完成,無需echo | cut

day=${fullyear:6:2}

答案2

我在包含檔案的目錄的根目錄中使用這個 shell 腳本,將它們全部移到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

以下一行將建立一個 shell 腳本,根據修改時間將檔案移至正確的資料夾。

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 之前,您可以對其進行編輯以刪除不需要的檔案。

相關內容