bash 如何在目标路径中使用通配符 (*) 使用 scp 进行复制?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40015807/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 15:18:30  来源:igfitidea点击:

How do I copy with scp with a wildcard(*) in the destination path?

bashshellcopywildcard

提问by pingul

Is it possible to get the value of what a wildcard matched to? I.e. I want to do

是否有可能获得通配符匹配的值?即我想做

scp -r user@host:some/path/with/*/file.txt cp/to/*/file.txt

With the command above, I want

使用上面的命令,我想要

some/path/with/TEST/file.txt --> cp/to/TEST/file.txt
some/path/with/OTHER/file.txt --> cp/to/OTHER/file.txt

EDIT:I'll add some more data of my actual setup, which might make it clearer.

编辑:我将添加一些实际设置的更多数据,这可能会使其更加清晰。

On my server I have the structure

在我的服务器上我有结构

server $ pwd
~/sixtrack/simulations
server $ ls
run0001
run0002
run0003
...

Each run*is a directory, containing files like run*/summary.dat, run*/tracks.datetc. I could copy everything over to my own computer like

run*一个目录,包含文件一样run*/summary.datrun*/tracks.dat等我可以复制一切交给我自己的电脑一样

pingul $ scp -r 'user@host:sixtrack/simulations/*' .

However, I would like to not copy over everyfile, instead just some. Because all files are named the same and only separated through the directory, I have to respect the structure. As such, I would like host:sixtrack/simulations/run0001/summary.datto go into my local folder /Users/pingul/Workspace/simulations/run0001/summary.dat.

但是,我不想复制每个文件,而只是复制一些。因为所有文件都命名相同,并且仅通过目录分隔,所以我必须尊重结构。因此,我想host:sixtrack/simulations/run0001/summary.dat进入我的本地文件夹/Users/pingul/Workspace/simulations/run0001/summary.dat

Running

跑步

pingul $ pwd
/Users/pingul/Workspace/simulations
pingul $ scp -r 'user@host:sixtrack/simulations/*/summary.dat' */.

Does not accomplish what I want. Adding the -voption as suggested prints out

没有完成我想要的。添加-v选项作为建议打印出来

Executing: cp -r -- run0001/. run0100/.
Executing: cp -r -- run0002/. run0100/.
Executing: cp -r -- run0003/. run0100/.
...

and I only get one summary.datin run0100. All other directories are empty (i.e. run0001, run0002, ...)

我只有一次summary.datrun0100。所有其他目录都是空的(即run0001, run0002, ...)

Is what I want possible?

我想要的可能吗?

采纳答案by Arkadiusz Drabczyk

It depends on whether you want to expand *beforerunning a command or afterrunning it and whether you want to do it interactively or not.

这取决于您是要*运行命令之前还是运行命令之后进行扩展,以及是否要以交互方式进行。

If you want to expand it beforerunning a command interactively you can either use insert-completions (M-*)or glob-expand-word (C-x *)described in man bash:

如果您想交互式运行命令之前扩展它您可以使用insert-completions (M-*)glob-expand-word (C-x *)描述man bash

   glob-expand-word (C-x *)
          The word before point is treated as a pattern for
          pathname expansion, and the list of matching filenames
          is inserted, replacing the word.  If a numeric argument
          is sup- plied, an asterisk is appended before pathname
          expansion.

   insert-completions (M-*)
          Insert all completions of the text before point that
          would have been generated by possible-completions.

To use these functions put a cursor before or after *and press either Control-x*or Alt-*:

要使用这些功能,请将光标放在之前或之后*,然后按Control-x*Alt- *

$ pwd
/tmp/expand-glob
$ ls
FILE
$ cp /tmp/expand-*/*

Now put your cursor after the last *, don't press Enterbut C-x*and you'll get this

现在把你的光标放在最后一个之后*,不要按Enter但是C-x*你会得到这个

$ cp /tmp/expand-glob/FILE

If you want to expand *to test command in the script then neither scpnor cpis a good option because the cannot run in dry-runmode. You should go with something like rsyncthat would show what files it wouldtransfer if it was actually run like this:

如果你想扩展*到脚本中的测试命令,那么这既不 是一个好选择,scp也不cp是一个好的选择,因为它不能在dry-run模式下运行。如果它实际上像这样运行rsync,你应该使用类似的东西来显示它传输哪些文件:

$ rsync  -vn --relative /tmp/expand-*/* .
/tmp/
/tmp/expand-scp/
/tmp/expand-scp/a
/tmp/expand-scp/b
/tmp/expand-scp/c
/tmp/expand-scp/mmmm32

EDIT:

编辑

How about this:

这个怎么样:

$ rsync -avn -R --rsync-path="cd sixtrack/simulations && rsync"  user@host:run*/summary.dat .

-nstands for dry-run. With this option rsyncwill only print how will recreate a remote directory structure in current directory. In your case it will be something like:

-n代表试运行。使用此选项rsync将只打印如何在当前目录中重新创建远程目录结构。在您的情况下,它将类似于:

receiving incremental file list
drwxr-xr-x          4,096 2016/10/13 12:45:36 run0001
-rw-r--r--              0 2016/10/13 12:23:18 run0001/summary.dat
drwxr-xr-x          4,096 2016/10/13 12:23:18 run00010
-rw-r--r--              0 2016/10/13 12:23:18 run00010/summary.dat
drwxr-xr-x          4,096 2016/10/13 12:23:18 run0002
-rw-r--r--              0 2016/10/13 12:23:18 run0002/summary.dat
drwxr-xr-x          4,096 2016/10/13 12:23:18 run0003
-rw-r--r--              0 2016/10/13 12:23:18 run0003/summary.dat
drwxr-xr-x          4,096 2016/10/13 12:23:18 run0004
-rw-r--r--              0 2016/10/13 12:23:18 run0004/summary.dat
drwxr-xr-x          4,096 2016/10/13 12:23:18 run0005
-rw-r--r--              0 2016/10/13 12:23:18 run0005/summary.dat
drwxr-xr-x          4,096 2016/10/13 12:23:18 run0006
-rw-r--r--              0 2016/10/13 12:23:18 run0006/summary.dat
drwxr-xr-x          4,096 2016/10/13 12:23:18 run0007
-rw-r--r--              0 2016/10/13 12:23:18 run0007/summary.dat
drwxr-xr-x          4,096 2016/10/13 12:23:18 run0008
-rw-r--r--              0 2016/10/13 12:23:18 run0008/summary.dat
drwxr-xr-x          4,096 2016/10/13 12:23:18 run0009
-rw-r--r--              0 2016/10/13 12:23:18 run0009/summary.dat

回答by Leon

What you're asking for is impossible since cp/scpcommands take only a single destination. However you can easily simulate it with some very straightforward scripting:

你要求的是不可能的,因为cp/scp命令只需要一个目的地。但是,您可以使用一些非常简单的脚本轻松模拟它:

for d in *
do
    scp -r user@host:some/path/with/"$d"/file.txt cp/to/"$d"/file.txt
done

It can also be written on a single line as

也可以单行写成

for d in *; do scp -r user@host:some/path/with/"$d"/file.txt cp/to/"$d"/file.txt; done