Skip to content

Instantly share code, notes, and snippets.

@shouya
Created March 17, 2012 08:49
Show Gist options
  • Save shouya/2056807 to your computer and use it in GitHub Desktop.
Save shouya/2056807 to your computer and use it in GitHub Desktop.
A batch operation script to sync the pictures from my phone to pc.
#!/bin/bash
: << DOC
This script does scan all the photo from my phone and pull them out into a
temporary directory. After then, it will arrange the photos into special
directory by taken date, and if the target directory does not exist, the script
will create one to store such files. Subsequently and optionally, it could
convert all the photos imported into wiki image size and put the outputs into
another temporary directory, and show me them to deal.
Special Tools Requirement:
* Android Debug Bridge (adb)
* wikiphoto (another script written by me)
* ImageMagick (convert)
* bc
* exiv2
Have fun!
DOC
# Configurations
## Environment Setting
use_sudo="yes"
open_program=gnome-open
## Target Directory Setting
target_dir="$HOME/Pictures/"
uncat_dir="$HOME/Pictures/else"
## Import Setting
need_root="no"
photo_dir="/sdcard/DCIM"
import_hidden_dir="no"
match_regex=".*\.(png|jp[e]?g)$"
## Wikify Setting
wikify="yes"
wikify_dir="$HOME/Pictures/wiki"
wikify_script="$HOME/script/wikiphoto"
## Others
open_dir_at_the_end="yes"
# Here is the END of configuration
# Program Body
# Do NOT modified the code below unless you know what you're doing
# global variables
_sub_dirs=
_tmp_dir=
_org_dir=`pwd`
_photo_lst=
_jpg_date=
_wikify_name=
# Functions
# Meta Functions
exec_cmd() {
cmd="$1"
(sleep 0.3; echo "$cmd"; echo exit) |
adb shell |
sed -e '1 d' -e '$ d'
}
clean_and_exit() {
[ -d "$_tmp_dir" ] && {
rm -rf "$_tmp_dir"
}
[ -z "$1" ] && exit 1 || exit $1
}
# chop last character of a line
chop() {
sed 's/.$//'
}
# check if file is a jpg
is_jpg() {
result="`file "$1" | grep -i 'JPEG' | wc -l`"
[ "$result" -eq "0" ] &&
return 1 ||
return 0
}
# acquire a jpg file's shooting date
jpg_date() {
jpg="$1"
[ ! -z "$(exiv2 "$jpg" 1>/dev/null 2>/dev/stdout)" ] && return 1
_jpg_date=$(
exiv2 "$jpg" 2>/dev/null |
grep timestamp |
sed -r -e 's/.*:\s//' \
-e 's/([0-9]{4}):([0-9]{2}):([0-9]{2}).*$/\1 \2 \3/'
)
[ -z "$_jpg_date" ] &&
return 1 ||
return 0
}
# get special field
get_field() {
awk "{print \$$1}"
}
# ask whether the file will be overrieded
ask_override() {
org="$1"
dst="$2"
o_ctime="`stat $org | sed -n '/^Change/p' |
sed -r 's/Change:\s(.*)\..*$/\1/'`"
d_ctime="`stat $dst | sed -n '/^Change/p' |
sed -r 's/Change:\s(.*)\..*$/\1/'`"
o_size="`stat $org | sed -n '/Size/p' |
sed -r 's/.*Size:\s([0-9]*).*/\1/'`"
d_size="`stat $dst | sed -n '/Size/p' |
sed -r 's/.*Size:\s([0-9]*).*/\1/'`"
echo "File conflict:"
echo " Original $org(ctime: $o_ctime, size: $o_size)"
echo " Destination $dst(ctime: $d_ctime, size: $d_size)"
echo -n "Do you want to override it (y/N): "
read user_input
case "$user_input" in
[yY]* ) return 0;;
[nN]* ) return 1;;
esac
return 1
}
wikify_name() {
org_name="$1"
_wikify_name=$(
echo $org_name |
sed -r 's/(.*)\.(.*)$/\1.wiki.\2/'
)
[ -z "$_wikify_name" ] && return 1
return 0
}
# Main implement starts here
# try to start adb deamon
start_server() {
echo -n "Restarting the server..."
[ "$need_root" = "yes" ] && {
[ "$use_sudo" = "yes" ] && {
sudo adb kill-server
sudo adb start-server > /dev/null
} || {
su -c "adb kill-server && adb start-server > /dev/null"
}
} || {
adb kill-server
adb start-server > /dev/null
}
[ "$?" -ne "0" ] && {
echo "Failed!"
return 1
} || {
echo "Succeed!"
return 0
}
}
# check device whether it is avalible, return 0 if succeed.
check_device() {
echo -n "Checking device connection..."
[ $(adb devices | wc -l) -ge '3' ] || {
echo "Failed!"
return 1
}
echo "Succeed!"
return 0
}
# check the photo directory if exists
check_photo_dir() {
echo -n "Checking photo directory..."
[ $(exec_cmd "cd $photo_dir" | wc -l) = "4" ] && {
echo "Failed!"
return 1
} || {
echo "Succeed!"
return 0
}
}
# list all the subdirectoris below the photo directoy on the device
list_sub_dir() {
dir_org=$(exec_cmd "ls -l -a $photo_dir" |
grep '^d' |
awk '{print $6}')
_sub_dirs=$(
[ "$import_hidden_dir" = "yes" ] && {
echo "$dir_org"
} || {
echo "$dir_org" | while read ln
do
[ -z "$(echo $ln | sed '/^\./d')" ] || {
echo $ln
}
done
} )
_sub_dirs=$(
echo "$_sub_dirs" | while read ln
do
echo "$photo_dir/$ln"
done
)
return 0
}
# make a temporary directory
make_temp_dir() {
echo -n "Making temporary directory..."
_tmp_dir="`mktemp -d`"
[ "$?" -ne "0" ] && {
echo "Failed!"
return 1
}
echo "Succeed!"
return 0
}
# transfer the files from device to the temporary directory
pull_files() {
echo "Transfering photos (this process may take long time)..."
echo "$_sub_dirs" | while read dir
do
dir=`echo "$dir" | chop`
echo "Now transfering: $dir"
adb pull "$dir" 2>/dev/null 1>/dev/null
[ "$?" -ne "0" ] && {
echo "Error when transfering $dir"
return 1
}
done
return 0
}
# scan all photos imported into a list
scan_photos() {
echo -n "Scanning photos imported..."
_photo_lst=$(find -regextype posix-extended \
-type f -a \
-iregex "$match_regex")
[ "$?" -ne 0 ] && {
echo "Failed!"
return 1
}
echo "Succeed!"
return 0
}
process_jpg() {
photo="$1"
jpg_date "$photo" || {
process_else "$photo"
return $?
}
year=`echo $_jpg_date | get_field 1`
month=`echo $_jpg_date | get_field 2`
date=`echo $_jpg_date | get_field 3`
target_file_dir="$target_dir/$year/$month/$date"
target="$target_file_dir/$photo"
# copying file to spcial directory
mkdir -p "$target_file_dir" 2>/dev/null
[ -e "$target" ] && {
[ `md5sum "$photo" | get_field 1` = \
`md5sum "$target" | get_field 1` ] && {
# skip the file
return 0
} || {
ask_override "$photo" "$target" &&
cp -f "$photo" "$target"
}
} || {
cp -f "$photo" "$target"
}
echo -n "Imported & categoried $photo"
# generate wiki image
[ "$wikify" != "yes" ] || wikify_name "$photo" || {
echo "."
return 0
}
mkdir -p "$wikify_dir" 2>/dev/null
$wikify_script "$photo" 1>/dev/null 2>/dev/null
mv -bf "$_wikify_name" "$wikify_dir" 2>/dev/null
echo " and wikified."
return 0
}
process_else() {
photo="$1"
mkdir -p "$uncat_dir" 2>/dev/null
target="$uncat_dir/$photo"
[ -e "$target" ] && {
[ `md5sum "$photo" | get_field 1` = \
`md5sum "$target" | get_field 1` ] && {
# skip the file
return 0
} || {
ask_override "$photo" "$target" &&
mv -f "$photo" "$target"
}
} || {
mv -f "$photo" "$target"
}
echo "Imported uncategoried $photo."
return 0
}
process_all_photos() {
echo "$_photo_lst" | while read photo
do
is_jpg "$photo" && {
process_jpg "$photo"
} || {
process_else "$photo"
}
done
return 0
}
open_output_dir() {
[ "$open_dir_at_the_end" != "yes" ] && return 0
$open_program "$target_dir"
}
# Main flow
start_server || clean_and_exit
check_device || clean_and_exit
check_photo_dir || clean_and_exit
list_sub_dir # || clean_and_exit
make_temp_dir || clean_and_exit
cd "$_tmp_dir" || clean_and_exit
pull_files || clean_and_exit
scan_photos || clean_and_exit
process_all_photos || clean_and_exit
open_output_dir || clean_and_exit
clean_and_exit
# EOF
# Shou Ya
# Morning Mar 17, 2012 yet another sleepless night!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment