我正在编写一个 bash 脚本,需要*_out.csv
从远程服务器上的目录中获取所有内容。所有这些文件都是另一个目录深处的几个目录。例如,假设该目录名为ox_20190404/
.我可以通过以下方式找到我的所有文件:
find ox_20190404/assessment/LWR/validation -type f -name "*_out.csv"
这个问题回答了我的部分问题,但由于我不想完整复制目录,所以我需要弄清楚如何实现上述代码。假设我从这个开始:
$ dir="/projects/ox/git"
$ server="myusername@server"
$ scp $server:$dir/$(ssh $server 'ls -t $dir | head -1') .
我如何从那里获取我需要的文件?
我的问题的最后一部分想知道是否有一种方法可以获取所有复制的文件并将它们放置在远程服务器上的相同文件路径和目录中。
答案1
我稍微调整了一些变量名称。
当然,有比像这样危险的事情更好的方法来做到这一点解析 ls 的输出,但看看这是否适合您:
$ pth="/projects/ox/git"
$ server="myusername@server"
$ dir="$(ssh $server "ls -t \"$pth\" | head -1")"
$ mkdir -p "$pth/$dir"
$ scp -p $server:"$pth/$dir"/'*_out.csv' "$pth/$dir"/
一旦dir
被设置为最新的远程目录,mkdir -p
用于确保本地存在相同的目录名。然后scp
将文件复制到与远程目录具有相同路径和名称的本地目录中。我一直在寻找 rsync 解决方案,但想不出一个。
答案2
这将找到最近修改(创建)的目录,假设目录名称不包含换行符 ( \n
)
newest=$(
ssh -qn REMOTE 'find ./* -mindepth 0 -maxdepth 0 -type d -printf "%T@\t%f\n"' |
sort -t$'\t' -r -nk1,2 |
head -n1 |
cut -f2-
)
如果您可以保证目标仅包含感兴趣的目录,您可以大大简化它(再次记住换行问题)
newest=$(ssh -qn REMOTE ls -t | head -n1)
您可以使用复制整个文件树scp
,但如果您想过滤它,您可能最好使用rsync
rsync -av --include '*/' --include '*_out.csv' --exclude '*' --prune-empty-dirs REMOTE:"$newest" "$newest"
如果您将前一组文件保留在本地,并且您确实只想添加最新的一组文件而不复制前一组文件,rsync
也可以这样做
rsync -av --include '*/' --include '*_out.csv' --exclude '*' --prune-empty-dirs REMOTE: .
答案3
这是最终为我工作的代码。我可能没有完美地描述我的问题,但我在找到最近更改的目录时没有遇到问题。我的问题是找到该目录中的所有文件并确保它们最终位于本地计算机上的正确位置。下面是执行此操作的 bash 脚本:
# Grab the most recently updated ox file off of server; return as string
# in the form of ox_XXXXXXXX/assessment/LWR/validation/*
newest=$(
ssh -qn username@server 'find /projects/ox/git/* -mindepth 0 -maxdepth 0 -type d -printf "%T@\t%f\n"' |
sort -t$'\t' -r -nk1,2 |
head -n1 |
cut -f2- |
awk '{print "/projects/ox/git/"$1"/assessment/LWR/validation/HBEP/analysis/BK363/*"}'
)
# Take $newest and find all associated *_out.csv files beneath that directory
newestf=$(
ssh -qn username@server "find $newest -type f -name '*_out.csv'"
)
# Write these filepaths to a .csv on the local machine
echo "$newestf" | tr " " "\n" remote_fp.csv
# Run Rscript to parse and transform the filepaths so they go to the write place on local machine
Rscript ~/transform_fp.R
# Read content from .csv remote file paths - we'll need these to actually pull the files using scp
get_scp_fp=$(awk -F "\"*,\"*" '{print $1}' ~/remote_fp.csv)
# Read content from .csv local file paths - we'll need these to actually write the data locally
get_local_fp=$(awk -F "\"*,\"*" '{print $1}' ~/local_fp.csv)
# Loop through file paths and pull data from remote to local.
for i in $get_scp_fp; do
for j in $get_local_fp; do
scp -p username@server:"$i" "$j"
done
done
脚本:
suppressPackageStartupMessages(library(tidyverse))
test <- read_csv("remote_fp.csv", col_names = FALSE)
str_replace_all(test$X1, "/projects/ox/git/ox_[0-9]{8}", "~/Documents/projects/ox") %>%
str_replace_all("(?:analysis).*$", paste0("doc/figures/", basename(.))) %>%
tibble() %>%
write_csv(path = "~/local_fp.csv", col_names = FALSE)