config.ini
저는 각각 파일과 JPEG 이미지를 포함하는 수천 개의 하위 디렉터리가 있는 디렉터리를 가지고 있습니다 . ini 파일에는 이미지가 촬영된 시간을 인코딩하는 섹션이 포함되어 있지만 이에 국한되지는 않습니다.
[Acquisition]
Name=coating_filtered_001
Comment=Image acquisition
Year=2017
Month=3
Day=21
Hour=13
Minute=2
Second=34
Milliseconds=567
이 질문의 경우 이미지 파일의 이름은 항상 동일합니다 image.jpg
.
모든 이미지 파일을 다른 (단일) 디렉토리에 복사하고 이름을 유사하거나 유사한 것으로 바꾸고 싶습니다 yyyy-mm-ddThh:mm:ss:NNN.jpg
. 즉, ini 파일의 타임스탬프로 구성된 파일 이름입니다.
명령줄에서 이를 달성할 수 있습니까?
답변1
그것할 수 있는명령줄에서 이 작업을 수행하는 것이 가능하지만 명령줄에서 스크립트를 실행하는 것이 더 간단한 해결책이 될 것입니다.
기본 단계:
반복할 디렉터리 목록을 가져옵니다.
find ${directory} -mindepth 1 -type d
각 디렉토리의 존재 여부를 확인
config.ini
합니다image.jpg
.
if [ -f ${subdir}/config.ini -a -f ${subdir}/image.jpg ]; then ...
- config.ini에서 타임스탬프의 올바른 부분을 모두 확인하세요.
다양grep ^Year= ${subdir}/config.ini
하거나^Month
등등... - 타임스탬프가 포함된 image.jpg 파일을 복사합니다.
cp ${subdir}/image.jpg ${copydir}/${timestamp}.jpg
나는 이러한 시퀀스를 스크립트에 넣는 것이 더 쉽고 안전하다고 생각합니다. 스크립트에서는 읽기 쉬운 출력, 오류 처리 등을 더 쉽게 넣을 수 있습니다.
다음은 이러한 단계를 수행하는 샘플 스크립트입니다.
#!/bin/bash
imagepath="/path/to/images"
copydir="/path/to/copies"
# step 1: find all the directories
for dir in $(find ${imagepath} -mindepth 1 -type d); do
echo "Procesing directory $dir:"
ci=${dir}/config.ini
jp=${dir}/image.jpg
# step 2: check for config.ini and image.jpg
if [ -f ${ci} -a -f ${jp} ]; then
# step 3: get the parts of the timestamp
year=$(grep ^Year= ${ci} | cut -d= -f2)
month=$(grep ^Month= ${ci} | cut -d= -f2)
day=$(grep ^Day= ${ci} | cut -d= -f2)
hour=$(grep ^Hour= ${ci} | cut -d= -f2)
min=$(grep ^Minute= ${ci} | cut -d= -f2)
sec=$(grep ^Second= ${ci} | cut -d= -f2)
ms=$(grep ^Milliseconds= ${ci} | cut -d= -f2)
# if any timestamp part is empty, don't copy the file
# instead, write a note, and we can check it manually
if [[ -z ${year} || -z ${month} || -z ${day} || -z ${hour} || -z ${min} || -z ${sec} || -z ${ms} ]]; then
echo "Date variables not as expected in ${ci}!"
else
# step 4: copy file
# if we got here, all the files are there, and the config.ini
# had all the timestamp parts.
tsfile="${year}-${month}-${day}T${hour}:${min}:${sec}:${ms}.jpg"
target="${copydir}/${tsfile}"
echo -n "Archiving ${jp} to ${target}: "
st=$(cp ${jp} ${target} 2>&1)
# capture the status and alert if there's an error
if (( $? == 0 )); then
echo "[ ok ]"
else
echo "[ err ]"
fi
[ ! -z $st ] && echo $st
fi
else
# other side of step2... some file is missing...
# manual check recommended, no action taken
echo "No config.ini or image.jpeg in ${dir}!"
fi
echo "---------------------"
done
실수로 파일을 삭제하지 않도록 이러한 스크립트를 사용할 때는 주의하는 것이 가장 좋습니다. 이 스크립트는 복사 작업을 1회만 수행하므로 매우 보수적이며 소스 파일을 손상시키지 않습니다. 그러나 필요에 따라 특정 작업을 변경하거나 메시지를 출력해야 할 수도 있습니다.
답변2
top="$(pwd -P)" \
find . -type d -exec sh -c '
shift "$1"
for iDir
do
cd "$iDir" && \
if [ -f "image.jpg" ] && [ -s "config.ini" ]; then
eval "$(sed -e "/^[[]Acquisition]/,/^Milliseconds/!d
/^Year=/b; /^Month=/b; /^Day=/b; /^Hour=/b; /^Minute=/b
/^Second=/b; /^Milliseconds=/b; d" config.ini)"
new=$(printf "%04d-%02d-%02dT%02d:%02d:%02d:%03d\n" \
"$Year" "$Month" "$Day" "$Hour" "$Minute" "$Second" "$Milliseconds")
echo cp -p "image.jpg" "$new"
cp -p "image.jpg" "$new"
else
#echo >&2 "$iDir/image.jpg &/or config.ini file(s) missing or empty."
:
fi
cd "$top"
done
' 2 1 {} +
#meth-2
find . -type f -name config.ini -exec perl -F= -lane '
push @A, $F[1] if /^\[Acquisition]/ .. /^Milliseconds/ and
/^(?:Year|Month|Day|Hour|Minute|Second|Milliseconds)=/;
next if ! eof;
my(@a, $fmt) = qw/- - T : : :/;
(my $d = $ARGV) =~ s|/[^/]+$||;
print( STDERR "No image.jpg in dir: $d"),next if ! -f $d . "/image.jpg";
$fmt .= "${_}$a[$a++]" for map { "%0${_}s" } qw/4 2 2 2 2 2 3/;
print for map { "$d/$_" } "image.jpg", sprintf "$fmt.jpg", @A;
($a,@A)=(0);
' {} + | xargs -n 2 echo mv