简体   繁体   English

android:使用 adb push 递归复制

[英]android: Recursive copy with adb push

I think adb's push is file-based.我认为 adb 的推送是基于文件的。 I want to be able to push entire folders.我希望能够推送整个文件夹。 Is there an easy way without scripting?没有脚本有没有简单的方法?

Thanks!谢谢!

Edit: I need to work with sub-folders.编辑:我需要使用子文件夹。

Edit: Seems that adb pull is recursive but push is not.编辑:似乎 adb pull 是递归的,但 push 不是。 So I changed the title and description accordingly.所以我相应地更改了标题和描述。

Try this (worked with subfolders):试试这个(使用子文件夹):

adb push mySourceFolder/. myDestAndroidFolder

Empty folders do not copy to android device.空文件夹不会复制到 android 设备。

I'm gonna dig this even more to give a full solution to this (for linux only), because google redirect to this and I had this exact same problem.我将进一步挖掘它以提供完整的解决方案(仅适用于 linux),因为谷歌重定向到这个,我遇到了同样的问题。

With a simple adb push, the problem is that all the subdirectories must exist BEFORE doing the push, which can be very painful to achieve.使用简单的 adb 推送,问题是在进行推送之前必须存在所有子目录,这可能会非常痛苦。

Note that an easy solution is to zip the folder, push the zip then unzip on the device.请注意,一个简单的解决方案是压缩文件夹,推动 zip 然后在设备上解压缩。 But let's say you don't have unzip on your device (highly unlikely, really).但是假设您的设备上没有解压缩(非常不可能,真的)。

You want to push a full tree with a lot of subdirectories to your device in an empty directory myDirectory.您想将包含大量子目录的完整树推送到设备的空目录 myDirectory 中。 There are two steps :有两个步骤:

First create all the subdirectories, in your source device:首先在源设备中创建所有子目录:

cd <folder-containing-myDirectory>
find myDirectory/ -type d -exec adb shell mkdir <path-to-folder-containing-myDirectory-in-device>/{} \;

This command find all the subdirectories of myDirectory (including ., so if myDirectory already exists, you will have one error message you can safely ignore) and for each of them, create the matching directory on the device.此命令查找 myDirectory 的所有子目录(包括 .,因此如果 myDirectory 已经存在,您将收到一条可以放心忽略的错误消息),并为每个子目录在设备上创建匹配的目录。

then push everything然后推动一切

adb push myDirectory/. <path-to-folder>/myDirectory

adb pull, pulls all the files in the specified directory: adb pull,拉取指定目录下的所有文件:

$ adb pull /mnt/sdcard/
pull: building file list...
pull: /mnt/sdcard/t3.txt -> ./t3.txt
pull: /mnt/sdcard/t2.txt -> ./t2.txt
pull: /mnt/sdcard/t1.txt -> ./t1.txt
3 files pulled. 0 files skipped.

or或者

$ adb push . /mnt/sdcard/
push: ./t2.txt -> /mnt/sdcard/t2.txt
push: ./t3.txt -> /mnt/sdcard/t3.txt
push: ./t1.txt -> /mnt/sdcard/t1.txt
3 files pushed. 0 files skipped.

Ran into this as well and found this article useful, but may have found a more complete solution.也遇到了这个问题,发现这篇文章很有用,但可能找到了更完整的解决方案。 Running the following from the folder containing the files/folders you want to push:从包含您要推送的文件/文件夹的文件夹中运行以下命令:

adb push . /myDestinationFolder

The key is the prefix '/' before the destination folder apparently.显然,关键是目标文件夹之前的前缀“/”。 This works from my windows command prompt, but when I run it from git bash (on Windows) I get some errors due to the meaning of the '/' in a path within the bash shell.这适用于我的 Windows 命令提示符,但是当我从 git bash(在 Windows 上)运行它时,由于 bash shell 中路径中的“/”的含义,我会遇到一些错误。 So this might not work from linux/bash, however it definitely copied all subfolders for me.所以这可能不适用于 linux/bash,但它肯定为我复制了所有子文件夹。

I realize this question is a little old and I'm about to mention scripting when the question excluded it, but I'm going to answer this anyway.我意识到这个问题有点老了,当问题排除它时,我将提到脚本,但无论如何我都会回答这个问题。 Mostly, because I wish I had found this answer here, before having to work it out myself.主要是因为我希望我能在这里找到这个答案,然后再自己解决。

adb push WILL work recursively, if all of the subfolders are present already.如果所有子文件夹都已经存在, adb push 将递归工作。 They can be empty, it just seems that adb push can not make folders.它们可以是空的,似乎 adb push 不能创建文件夹。 I found this to be a useful distinction because one could run a series of commands like this:我发现这是一个有用的区别,因为可以运行如下一系列命令:

$ adb shell mkdir /folder
$ adb shell mkdir /folder/sub1
$ adb shell mkdir /folder/sub2
$ adb push folder

So, yes, one could make a small wrapper script to do this automatically.所以,是的,可以制作一个小包装脚本来自动执行此操作。 However, I think the more important point is that it just requires the folders to be there.但是,我认为更重要的一点是它只需要文件夹在那里。 Which means that if this is something that you are going to update multiple times in the same folder.这意味着如果这是您要在同一个文件夹中多次更新的内容。 For instance, adding pictures to an existing subfolder structure would work great over and over again with the single adb push command.例如,将图片添加到现有的子文件夹结构将使用单个 adb push 命令一遍又一遍地工作。

To expand on autra 's genius answer a bit, I made a quick script to automate this (for Linux/Mac only).为了稍微扩展autra的天才答案,我制作了一个快速脚本来自动执行此操作(仅适用于 Linux/Mac)。

I created an empty file in my home directory called adb-push .我在我的主目录中创建了一个名为adb-push的空文件。 Then I edited the file with a text editor (like gedit, nano, vim, etc.) and put the following contents into it:然后我用文本编辑器(如 gedit、nano、vim 等)编辑了该文件,并将以下内容放入其中:

#!/bin/bash

# Usage:
# adb-push <directory-on-computer-to-send> <directory-on-device-to-receive-it>
# Example:
# adb-push ~/backups/DCIM /sdcard

src="${1}";
trgt="$(basename ${1})";
dst="$(echo "${2}" | grep '/$')";
# If ${dst} ends with '/', remove the trailing '/'.
if [ -n "${dst}" ]; then
    dst="${dst%/*}";
fi;

# If ${src} is a directory, make directories on device before pushing them.
if [ -d "${src}" ]; then
    cd "${src}";
    cd ..;
    trgt="${trgt}/";
    find "${trgt}" -type d -exec adb shell mkdir "${dst}/{}" \;
fi;

adb push "${src}" "${dst}/${trgt}";

Then I made it executable:然后我让它可执行:

chmod +x ~/adb-push;

This is how I run it:这就是我运行它的方式:

~/adb-push <directory-on-computer-to-send> <directory-on-device-to-receive-it>

For example, if I want to send " ~/backups/DCIM " to my device's sdcard folder, I would do this:例如,如果我想将“ ~/backups/DCIM ”发送到我设备的 sdcard 文件夹,我会这样做:

~/adb-push ~/backups/DCIM /sdcard

(But keep in mind that the location of the sdcard is not " /sdcard " for every Android device. For instance, it might be " /mnt/sdcard " instead.) (但请记住,对于每个 Android 设备,sdcard 的位置并不是“ /sdcard ”。例如,它可能是“ /mnt/sdcard ”。)

It has been a few years, the issues may or may not have changed, but it is still a PITA.几年过去了,问题可能会或可能不会改变,但它仍然是 PITA。 What is working for me on linux is to create a temp folder, create a symlink to the folder(s) I want to copy, and then I adb push.在 linux 上对我有用的是创建一个临时文件夹,创建一个指向我要复制的文件夹的符号链接,然后我 adb push。 It ignores the main dir, but copies the subdirs.它忽略主目录,但复制子目录。 Currently, I'm not needing to create any subdirs, they do get created and copied for me.目前,我不需要创建任何子目录,它们会为我创建和复制。 That might be platform specific, I'm not sure.这可能是特定于平台的,我不确定。 But the main dir I'm copying, it copies the files in it instead of the dir.但是我正在复制的主目录,它复制其中的文件而不是目录。 So the temp dir gets ignored, and the symlinked folders then get copied.因此临时目录被忽略,然后复制符号链接文件夹。 Example: mkdir tmp cd tmp ln -s ../Foo . ln -s ../Bar . cd .. adb push tmp /sdcard/示例: mkdir tmp cd tmp ln -s ../Foo . ln -s ../Bar . cd .. adb push tmp /sdcard/ mkdir tmp cd tmp ln -s ../Foo . ln -s ../Bar . cd .. adb push tmp /sdcard/ mkdir tmp cd tmp ln -s ../Foo . ln -s ../Bar . cd .. adb push tmp /sdcard/ And it will push Foo/file1 to /sdcard/Foo/file1 With just adb push Foo/. mkdir tmp cd tmp ln -s ../Foo . ln -s ../Bar . cd .. adb push tmp /sdcard/它会将 Foo/file1 推送到 /sdcard/Foo/file1 只需 adb push Foo/。 /sdcard/ then I end up with /sdcard/file1 which doesn't make me happy. /sdcard/ 然后我得到 /sdcard/file1 这并不让我高兴。

怎么样:存档->推送->提取

export FOLDER="Books"
TMPIFS="$IFS"
IFS=$'\n'
for i in `find "$FOLDER"/ -type d | sed 's,//\+,/,g'`; do
  adb shell mkdir -p /mnt/sdcard/"$i"
done && \
adb push "$FOLDER"/ /mnt/sdcard/"$FOLDER"
unset FOLDER
IFS="$TMPIFS"

I couldn't find a solution so I made one:我找不到解决方案,所以我做了一个:

from ppadb.client import Client as AdbClient
adb = AdbClient(host='127.0.0.1', port=5037)
devices = adb.devices()    #List of all connected devices
import os
import glob

def send_over_adb(device,hostpath,devpath="/storage/emulated/0/"):      # Recursively send folder and files over adb
    if os.path.isfile(hostpath):
        devpath = os.path.join(devpath,hostpath).replace('\\','/') # optimization for windows
        device.push(hostpath, devpath)
    elif os.path.isdir(hostpath):
        for i in glob.glob(hostpath+'\*'):
            print(i)
            send_over_adb(device,i,devpath)
    device.shell('am broadcast -a android.intent.action.MEDIA_MOUNTED -d file:///mnt/sdcard')
    device.shell('am force-stop com.android.gallery3d') #force create thumbnails

This function recursively sends over the folders and files while maintaining folder structure and ignores empty directories.此函数递归地发送文件夹和文件,同时保持文件夹结构并忽略空目录。

Limitation: file name shouldn't contain forward or back slashes(idk if any os allows that though)限制:文件名不应包含正斜杠或反斜杠(如果有任何操作系统允许,则为 idk)

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

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