简体   繁体   English

使用 adb 从手机相机传输照片的脚本

[英]Script that will transfer photos from phone camera using adb

Story故事

I take photos and record videos with my phone camera and keep all of them on my internal storage/sdcard.我用手机摄像头拍照和录制视频,并将所有这些都保存在我的内部存储/sdcard 中。 I periodically back them up on my PC, so I keep these camera photos on PC storage in sync with phone storage.我会定期将它们备份到我的 PC 上,因此我将这些相机照片保存在 PC 存储中与手机存储同步。

For years, I've been backing up my phone camera photos to my PC in the following way:多年来,我一直通过以下方式将手机相机照片备份到我的 PC:

  1. Plug in phone into PC and allow access to phone data将手机插入电脑并允许访问手机数据
  2. Browse phone storage → DCIM → Camera浏览手机存储 → DCIM → 相机
  3. Wait several minutes for the system to load a list of ALL photos等待几分钟让系统加载所有照片的列表
  4. Copy only several latest photos which haven't been backed up yet只复制几张尚未备份的最新照片

I figured that waiting several minutes for all photos to load is an unnecessary drag so I downloaded adb platform tools .我认为等待几分钟加载所有照片是不必要的拖累,所以我下载了adb 平台工具 I've added the folder bin to my Path environment variable (ie %USERPROFILE%\\Tools\\adb-platform-tools_r28.0.3 ) so that I can seamlessly use adb and not write its full path each time.我已将文件夹 bin 添加到我的Path环境变量(即%USERPROFILE%\\Tools\\adb-platform-tools_r28.0.3 ),以便我可以无缝地使用adb而不是每次都写出它的完整路径。

The script剧本

I wrote the following script for Git Bash for Windows.我为 Windows 版Git Bash编写了以下脚本。 It is also compatible with Unix if you change the $userprofile variable.如果您更改$userprofile变量,它也与 Unix 兼容。 Essentially, the script pulls camera photos between two dates from phone storage to PC .本质上,该脚本将两个日期之间的相机照片从手机存储中提取到 PC 中

# 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"

The problem问题

When I run the script ( bash adb-pull-camera-photos.sh ), everything runs smoothly except for the adb pull command in the while -loop.当我运行该脚本( bash adb-pull-camera-photos.sh ),一切运行顺利除adb pull的命令while -loop。 It gives the following error :它给出了以下错误

': 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

I am not sure why the output is broken.我不确定为什么输出被破坏了。 Sometimes when I resize the Git Bash window some of the text goes haywire.有时当我调整 Git Bash 窗口的大小时,一些文本会变得混乱。 This is the actual error text:这是实际的错误文本:

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

I am sure that these files exist in the specified directory on the phone.我确定这些文件存在于手机上的指定目录中。 When I manually execute the failing command in bash, it succeeds with the following output :当我在 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)

The question问题

I can't figure out what's wrong with the script.我无法弄清楚脚本有什么问题。 I thought the Windows system might be causing a commotion, because I don't see the reason why the same code works when entered manually, but doesn't work when run in a script.我认为Windows系统可能会引起骚动,因为我不明白为什么手动输入时相同的代码有效,但在脚本中运行时不起作用。 How do I fix this error?我该如何解决这个错误?

Additional info附加信息

  • Note that I had to use // in the beginning of an absolute path on Windows because Git Bash would interpret / as its own root directory ( C:\\Program Files\\Git ).请注意,我必须在 Windows 上绝对路径的开头使用//因为 Git Bash 会将/解释为它自己的根目录( C:\\Program Files\\Git )。
  • I've echo ed all variables inside the script and got all the correct paths that otherwise work via manual method.我已经echo了脚本中的所有变量,并获得了所有正确的路径,否则这些路径可以通过手动方法工作。

camera-ls.txt file contents camera-ls.txt 文件内容

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

Additional questions其他问题

  1. Is it possible to navigate to external sdcard without using its name?是否可以在不使用其名称的情况下导航到外部 SD 卡? I had to use /storage/06CB-C9CE/ because /sdcard/ navigates to internal storage.我不得不使用/storage/06CB-C9CE/因为/sdcard/导航到内部存储。
  2. Why does tr "\\\\" "/" give me this error: tr: warning: an unescaped backslash at end of string is not portable ?为什么tr "\\\\" "/"给我这个错误: tr: warning: an unescaped backslash at end of string is not portable

The problem was with Windows line delimiters . 问题出在Windows行定界符上

Easy fix 容易修复

Just add the IFS=$'\\r\\n' above the loop so that the read command knows the actual line delimiter. 只需在循环上方添加IFS=$'\\r\\n' ,以使read命令知道实际的行定界符。

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

Explanation 说明

I tried plugging the whole while -loop into the console and it failed with the same error: 我尝试将整个while -loop插入控制台,但由于相同的错误而失败:

$ 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 time I started investigating why the output was broken . 这次我开始调查为什么输出中断了 I remembered that windows uses \\r\\n as newline, which means Carriage Return + Line Feed, (CR+LF) , so some text must have been overwritten. 我记得Windows使用\\r\\n作为换行符,这意味着回车+换行(CR + LF) ,因此某些文本必须已被覆盖。

It was because of broken values stored inside the $filename variable. 这是因为$filename变量中存储的值损坏。

This is the loop from the script: 这是脚本的循环:

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

Since each iteration of the while -loop reads a line from $lsFile in the following form: 由于while -loop的每次迭代都以以下形式从$lsFile读取一行:

exampleFilename.jpg\r\n

It misinterprets the newline symbols as part of the file name, so adb pull tries to read files with these whitespaces in their names, but fails and it additionally writes a broken output. 它将换行符号误解为文件名的一部分,因此adb pull尝试读取名称中带有这些空格的文件,但是失败,并且还会写入损坏的输出。

Windows batch script Windows批处理脚本

Here's a .bat script that can be run by Windows Command Prompt or Windows PowerShell . 这是一个.bat脚本,可以由Windows命令提示符Windows PowerShell运行 No Git Bash required. 无需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%
  • Just edit the srcFolder to point to your phone camera folder, 只需编辑srcFolder以指向您的手机摄像头文件夹,
  • plug a pattern into the dateRegex for matching the date interval and 将一个模式插入dateRegex以匹配日期间隔和
  • save it as a file with .bat extension, ie: adb-pull-camera-photos.bat . 将其另存为扩展名为.bat的文件,即: adb-pull-camera-photos.bat
  • Double-click the file and it will pull filtered photos into CameraPhotos folder on Desktop. 双击该文件,它将过滤后的照片拖到桌面上的CameraPhotos文件夹中。

Keep in mind that you still need have adb for Windows on your PC. 请记住,您的PC上仍然需要Windows的adb

Adb Photo Sync亚行照片同步

This might not be the answer but might be useful for others looking for android photo/files backup solution.这可能不是答案,但可能对其他寻找 android 照片/文件备份解决方案的人有用。

I use this script on my Windows with git bash.我在我的 Windows 上使用 git bash 使用这个脚本。 This can be easily used for Linux.这可以很容易地用于 Linux。 A common issue with a long backup process is that it might get interrupted and you might have to restart the entire copy process from start.长时间备份过程的一个常见问题是它可能会中断,您可能必须从头开始重新启动整个复制过程。

This script saves you from this trouble.这个脚本可以让你免于这个麻烦。 You can restart the script or interrupt in between but it will resume copy operation from the point it left.您可以重新启动脚本或在两者之间中断,但它会从它离开的点恢复复制操作。

Just change the rfolder => android folder, lfolder => local folder只需更改 rfolder => android 文件夹,lfolder => 本地文件夹

#!/bin/sh

rfolder=sdcard/DCIM/Camera
lfolder=/f/mylocal/s8-backup/Camera

adb shell ls "$rfolder" > android.files

ls -1 "$lfolder" > local.files

rm -f update.files
touch update.files

while IFS=  read -r q; do
  # Remove non-printable characters (are not visible on console)
  l=$(echo ${q} | sed 's/[^[:print:]]//')
  # Populate files to update
  if ! grep -q "$l" local.files; then         
    echo "$l" >> update.files
  fi  
done < android.files

script_dir=$(pwd)
cd $lfolder

while IFS=  read -r q; do
  # Remove non-printable characters (are not visible on console)
  l=$(echo ${q} | sed 's/[^[:print:]]//')
  echo "Get file: $l"
  adb pull "$rfolder/$l"
done < "${script_dir}"/update.files

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM