Скрипт, который будет передавать фотографии с камеры телефона с помощью ADB - PullRequest
2 голосов
/ 20 июня 2019

История

Я снимаю фотографии и записываю видео с помощью камеры телефона и сохраняю их все на своей SDCard. Я периодически копирую их на свой компьютер, поэтому синхронизирую фотографии с камер на ПК и синхронизирую их с телефоном.

В течение многих лет я выполнял резервное копирование фотографий с телефона на свой компьютер следующим образом:

  1. Подключите телефон к ПК и разрешите доступ к данным телефона
  2. Просмотр SDCard → DCIM → Камера
  3. Подождите несколько минут , пока система загрузит список ВСЕХ фотографий
  4. Скопируйте только несколько последних фотографий, которые еще не были зарезервированы

Я подумал, что ждать несколько минут для загрузки всех фотографий - это ненужное перетаскивание , поэтому я скачал инструменты платформы adb . Я добавил папку bin в переменную окружения Path (то есть %USERPROFILE%\Tools\adb-platform-tools_r28.0.3), чтобы я мог без проблем использовать adb и не записывать полный путь каждый раз.

Сценарий

Я написал следующий скрипт для Git Bash для Windows. Он также совместим с Unix, если вы измените переменную $userprofile. По сути, скрипт переносит фотографии с камеры между двумя датами с телефона на ПК .

# Attach device and start deamon process
adb devices

# Initialize needed variables
userprofile=$(echo "$USERPROFILE" | tr "\\" "/") # Windows adjustments

srcFolder="//storage/06CB-C9CE/DCIM/Camera"    # Remote folder
dstFolder="$userprofile/Desktop/CameraPhotos"  # Local folder
lsFile="$dstFolder/camera-ls.txt"
filenameRegex="2019061[5-9]_.*"  # Date from 20190615 to 20190619

# Create dst folder if it doesn't exist
mkdir -p "$dstFolder"

# 1. List contents from src folder
# 2. Filter out file names matching regex
# 3. Write these file names line by line into a ls file
adb shell ls "$srcFolder" | grep -E "$filenameRegex" > "$lsFile"

# Pull files listed in ls file from src to dst folder
while read filename; do
  if [ -z "$filename" ]; then continue; fi
  adb pull "$srcFolder/$filename" "$dstFolder" # adb: error: ...
done < "$lsFile"

# Clean up
rm "$lsFile"

# Inform the user
echo "Done pulling files to $dstFolder"

проблема

Когда я запускаю сценарий (bash adb-pull-camera-photos.sh), все работает без сбоев, кроме команды adb pull в цикле while. выдает следующую ошибку :

': No such file or directoryemote object '//storage/06CB-C9CE/DCIM/Camera/20190618_124656.jpg
': No such file or directoryemote object '//storage/06CB-C9CE/DCIM/Camera/20190618_204522.jpg
': No such file or directoryemote object '//storage/06CB-C9CE/DCIM/Camera/20190619_225739.jpg

Я не уверен, почему вывод не работает. Иногда, когда я изменяю размер окна Git Bash, часть текста становится ненужной. Это фактический текст ошибки:

adb: error: failed to stat remote object '//storage/06CB-C9CE/DCIM/Camera/20190618_124656.jpg': No such file or directory
adb: error: failed to stat remote object '//storage/06CB-C9CE/DCIM/Camera/20190618_204522.jpg': No such file or directory
adb: error: failed to stat remote object '//storage/06CB-C9CE/DCIM/Camera/20190619_225739.jpg': No such file or directory

Я уверен, что эти файлы существуют в указанном каталоге на телефоне. Когда я вручную выполняю неудачную команду в bash, это приводит к следующему выводу :

$ adb pull "//storage/06CB-C9CE/DCIM/Camera/20190618_124656.jpg" "C:/Users/User/Desktop/CameraPhotos/"
//storage/06CB-C9CE/DCIM/Camera/20190618_124656.jpg: 1 file pulled. 15.4 MB/s (1854453 bytes in 0.115s)

Вопрос

Я не могу понять, что не так со сценарием. Я думал, что система Windows может вызывать суету, потому что я не вижу причины, по которой тот же код работает при вводе вручную, но не работает при запуске в сценарии. Как мне исправить эту ошибку?

Дополнительная информация

  • Обратите внимание, что мне пришлось использовать // в начале абсолютного пути в Windows, потому что Git Bash интерпретировал бы / как свой собственный корневой каталог ( C: \ Program Files \ Git ).
  • Я echo отредактировал все переменные внутри скрипта и получил все правильные пути, которые в противном случае работают ручным методом.

содержимое файла camera-ls.txt

20190618_124656.jpg
20190618_204522.jpg
20190619_225739.jpg

Дополнительные вопросы

  1. Можно ли перейти к внешней SD-карте, не используя ее имя? Мне пришлось использовать /storage/06CB-C9CE/, потому что /sdcard/ перемещается во внутреннюю память.
  2. Почему tr "\\" "/" выдаёт мне эту ошибку: tr: warning: an unescaped backslash at end of string is not portable?

Ответы [ 2 ]

0 голосов
/ 20 июня 2019

Windows пакетный скрипт

Вот сценарий .bat, который можно запустить с помощью Командная строка Windows или Windows PowerShell . Git Bash не требуется.

:: Start deamon of the device attached
adb devices

:: Pull camera files starting from date
set srcFolder=/storage/06CB-C9CE/DCIM/Camera
set dstFolder=%USERPROFILE%\Desktop\CameraPhotos
set lsFile=%USERPROFILE%\Desktop\CameraPhotos\camera-ls.txt
set dateRegex=2019061[5-9]_.*

mkdir %dstFolder%
adb shell ls %srcFolder% | adb shell grep %dateRegex% > %lsFile%
for /F "tokens=*" %%A in (%lsFile%) do adb pull %srcFolder%/%%A %dstFolder%
del %lsFile%
echo Done pulling files to %dstFolder%
  • Просто отредактируйте srcFolder, чтобы он указывал на папку камеры вашего телефона,
  • вставьте шаблон в dateRegex для сопоставления интервала даты и
  • сохранить как файл с расширением .bat, т.е. adb-pull-camera-photos.bat.
  • Дважды щелкните файл, и он перетянет отфильтрованные фотографии в папку CameraPhotos на рабочем столе.

Имейте в виду, что вам все еще нужно иметь adb для Windows на вашем ПК.

0 голосов
/ 20 июня 2019

Проблема была с Разделителями строк Windows .

Простое исправление

Просто добавьте IFS=$'\r\n' над циклом, чтобы команда read знала фактическуюразделитель строки.

IFS=$'\r\n'
while read filename; do
  if [ -z "$filename" ]; then continue; fi
  adb pull "$srcFolder/$filename" "$dstFolder"
done < "$lsFile"

Пояснение

Я попытался подключить весь while -петл в консоль, и он не удался с той же ошибкой:

$ bash adb-pull-camera-photos.sh
List of devices attached
9889db343047534336      device

tr: warning: an unescaped backslash at end of string is not portable
': No such file or directoryemote object '//storage/06CB-C9CE/DCIM/Camera/20190618_124656.jpg
': No such file or directoryemote object '//storage/06CB-C9CE/DCIM/Camera/20190618_204522.jpg
': No such file or directoryemote object '//storage/06CB-C9CE/DCIM/Camera/20190619_225739.jpg
Done pulling files to C:/Users/User/Desktop/CameraPhotos

Thisвремя, когда я начал исследовать, почему вывод был сломан .Я вспомнил, что Windows использует \r\n в качестве новой строки, что означает возврат каретки + перевод строки, (CR + LF) , поэтому некоторый текст должен быть перезаписан.

Это произошло из-за неработающейзначения хранятся в переменной $filename.

Это цикл из скрипта:

while read filename; do
  if [ -z "$filename" ]; then continue; fi
  adb pull "$srcFolder/$filename" "$dstFolder"
done < "$lsFile"

Поскольку каждая итерация while -loop читает строку из $lsFile вследующая форма:

exampleFilename.jpg\r\n

Он неправильно интерпретирует символы новой строки как часть имени файла, поэтому adb pull пытается прочитать файлы с этими пробелами в их именах, но завершается неудачно и дополнительно записывает неверный вывод.

...