在一个目录“my_directory”中,其中有其他目录,具有多层嵌套,我想通过模式查找一些文件,然后将它们一一上传到远程服务器。在远程服务器上,它们应该复制到同一台服务器上相对于远程的路径 my_directory
。为此,我将scp
我是从这个开始的:
ls -al my_directory | grep "*.my_custom."
尽管其中包含部分文件*.my_custom.
存在,但它什么也没返回。
我怎么能够:
a) 通过某种模式找到这些文件
b) 在 bash 中循环枚举它们,这样我就可以将每个变量引用为变量?以便下一步将其上传到服务器。
答案1
您的方法存在两个问题:
grep
尽管grep
需要正则表达式,但您在调用中使用了通配符(也称为“通配符”) 。这两个是不同的。在 glob 中,*
表示“任意字符和任意长度的字符串”,而在正则表达式中,表示“零个或多个前面的字符”,*
如果没有前面的字符,则表示文字。相反,.
glob 中的 表示文字.
,而在正则表达式中表示“任何单个字符”。因此,您grep
将查找字面上包含星号的文件,然后查找任何单个字符,然后my_custom
一遍又一遍地查找任何单个字符。对于您想要实现的匹配,正则表达式将是.*\.my_custom\.
或者,因为你没有锚定它,所以简单地
\.my_custom\.
您希望在 shell 脚本中使用生成的列表进行进一步处理。正如@Panki 已经注意到的,你应该从不解析的输出
ls
为此,它会偶然发现带有特殊字符的文件名。幸运的是,您可以返回到最初使用 glob 的尝试,并直接在 shell 中迭代文件:for file in *.my_custom.* do your_upload_command "$file" done
请注意,shell 变量
$file
放在双引号中。这是为了确保不会发生不需要的分词,即您的 shell 脚本不会偶然发现文件名中的空格或任何其他特殊字符。由于您声明要递归地执行此操作,因此可以通过对 shell 脚本进行较小的更改来实现这一点,方法是使用
globstar
shell 选项,自 Bash v4 起可用:shopt -s globstar for file in **/*.my_custom.* do your_upload_command "$file" done
答案2
这可以通过find
.
find my_directory -name "*.my_custom." -type f -exec scp -i {} <username>@<host>:<path>/{} \;
{}
将包含从 my_directory 开始的匹配文件的路径。exec
指定每场比赛要执行的命令。您可以修改您的scp
路径,记住这两点。
答案3
我会这样做(在 GNU 系统上):
(cd my_directory && find . -name '*.my_custom.*' -type f -print0) |
tar --null -T - -cf - | gzip -1 | ssh host 'cd my_directory && tar zxf -'