Bash 使用(scp | rsync)在创建文件夹结构的同时提取特定文件?

Bash 使用(scp | rsync)在创建文件夹结构的同时提取特定文件?,bash,unix,rsync,scp,Bash,Unix,Rsync,Scp,我有一个大型项目,托管在一个服务器上,该服务器上有特定的文件,我想将这些文件复制到本地机器上的相同文件夹结构中,但只复制我想要的特定文件。查找这些文件的当前命令是(在服务器上的项目中): 这将生成如下列表(为简洁起见,已截断): 我想使用scp或rsync将这些文件拉到我的本地计算机上,并创建文件夹结构,其中没有任何其他内容。最好的办法是什么?我有一大堆文件,所以我不想事先创建文件夹结构。我也不能从服务器上拉整个项目,因为它太大了,系统管理员会生我的气 有没有一种方法可以在本地计算机上同时创建文

我有一个大型项目,托管在一个服务器上,该服务器上有特定的文件,我想将这些文件复制到本地机器上的相同文件夹结构中,但只复制我想要的特定文件。查找这些文件的当前命令是(在服务器上的项目中):

这将生成如下列表(为简洁起见,已截断):

我想使用
scp
rsync
将这些文件拉到我的本地计算机上,并创建文件夹结构,其中没有任何其他内容。最好的办法是什么?我有一大堆文件,所以我不想事先创建文件夹结构。我也不能从服务器上拉整个项目,因为它太大了,系统管理员会生我的气


有没有一种方法可以在本地计算机上同时创建文件夹结构的同时提取这些文件?

我想您可以使用
rsync
--排除
--包括
选项来完成

rsync --recursive --include '*_out.csv' --exclude '*/doc/*' server:path/to/remote/dir path/to/local/dir

我鼓励
rsync
,我可能会通过
ssh
调用
find
,使用
basedir
在进程替换中从中提取文件。然后,您可以在
while
循环中读取服务器上找到的每个文件名,获取路径并使用
mkdir-p
(带验证)在本地计算机上当前目录下创建路径。然后可以调用
rsync
,使用
rsync-uav
将文件从服务器拉到正确的目录。例如,您可以执行类似的操作:

#!/bin/bash

server=${1:-yourserver}       ## your server name
basedir=${2:-/path/to/files}  ## the base directory to run find on server

while read -r line; do        ## read line at a time from find output on server
    dname="${line%/*}"        ## separate directory name
    mkdir -p "$dname" || {    ## create/validate directory from remote file
        printf "error: unable to create '%s'.\n", "$dname" >&2
        continue
    }
    rsync -uav "$server:$line" "$dname" ## rsync file to correct directory
done < <(ssh "$server" "find $basedir -type f -name '*_out.csv' ! -path './*/doc/*' 2>/dev/null")
#/bin/bash
服务器=${1:-yourserver}##您的服务器名称
basedir=${2:-/path/to/files}##要在服务器上运行find的基本目录
而read-r行;在服务器上查找输出时,一次读取一行
dname=“${line%/*}”##单独的目录名
mkdir-p“$dname”|{###从远程文件创建/验证目录
printf“错误:无法创建“%s”。\n”、“$dname”>&2
持续
}
rsync-uav“$server:$line”“$dname”##rsync文件到正确的目录

使用
dirname
提取路径名的目录部分,并使用
mkdir-p
创建本地目录结构。然后使用
rsync
scp
将文件复制到该目录。我认为您可以使用
rsync
以及
-include
-exclude
选项将文件复制到您想要的目录中。我通常会这样做。我唯一不清楚的是,如果路径的初始部分不存在,是否会有本地计算机上不存在的目录树的零散分支不会自动创建(例如,从本地计算机上的一个空目录开始,并尝试
rsync-uav/path/to/file/with/multive/dirs/to/file.txt
。在这种情况下,您需要在
rsync
调用之前在本地创建
/path/to/file/with/multive/dirs/to
的部分).
rsync
将自动创建任何所需的中间目录。除非中间路径不存在,并且您正在按名称复制单个文件,例如(
rsync-uav valkyrie:/home/david/tmp/ttt/CMakeFiles/TicTacToe.dir/link.txt ttt/CMakeFiles/TicTacToe.dir/
)如果本地不存在
ttt/CMakeFiles/TicTacToe.dir/
,则会导致
rsync:mkdir”/home/david/tmp/ttt/CMakeFiles/TicTacToe.dir“失败:没有此类文件或目录(2)
但我没有按名称复制单个文件。我使用
--recursive
选项复制整个目录层次结构,但将其筛选为他想要的文件。是的,没错,我知道,这正是我在问题中看到的差异,如果我错误地解释了问题,我会感到困惑。我用它来引出所有
*\u out.csv
可能分散在提问者正在查看的基本目录下的所有文件。Re你的最后一句话:你的意思是我在脚本中定义了一些东西,比如,
line=($(ssh-qn)user@server“find/path/to/files-type f-name'*\u out.csv'-not-path'*/doc/*'2>/dev/null”))
,这就是我将使用while循环迭代的内容?是的。请参阅我添加的最后一段。如果您只是复制整个目录,则只需一个
rsync
调用即可(如Barmar在回答中所示)。但是,如果要从远程计算机上的嵌套目录结构复制分散的文件,则需要在文件上循环(如上所述),并手动创建要复制到的路径。-
rsync
通常不会创建嵌套目录来复制文件(如果要复制整个基本目录,则会)。谢谢,这帮了我很大的忙。另一个答案似乎是可行的,但它最终复制了所有内容,而不仅仅是
*.\u out.csv
文件。您是否可以为
<提供资源?当然,这只是一个名为process substitution的bash功能。您可以重定向process substitution的输出以提供
>而
循环就像重定向文件一样。对于文件,您将执行
,对于进程替换,您将使用
<
rsync --recursive --include '*_out.csv' --exclude '*/doc/*' server:path/to/remote/dir path/to/local/dir
#!/bin/bash

server=${1:-yourserver}       ## your server name
basedir=${2:-/path/to/files}  ## the base directory to run find on server

while read -r line; do        ## read line at a time from find output on server
    dname="${line%/*}"        ## separate directory name
    mkdir -p "$dname" || {    ## create/validate directory from remote file
        printf "error: unable to create '%s'.\n", "$dname" >&2
        continue
    }
    rsync -uav "$server:$line" "$dname" ## rsync file to correct directory
done < <(ssh "$server" "find $basedir -type f -name '*_out.csv' ! -path './*/doc/*' 2>/dev/null")