수많은 파일을 날짜 구조의 디렉토리 순서로 이동합니다.

수많은 파일을 날짜 구조의 디렉토리 순서로 이동합니다.

이 디렉토리에는 약 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

나는 파일이 들어 있는 디렉토리의 루트에서 이 쉘 스크립트를 사용하여 모든 파일을 year/month-like 구조로 이동합니다.

#!/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를 실행하기 전에 이를 편집하여 원하지 않는 파일을 제거할 수 있습니다.

관련 정보