要删除远程 Linux 机器上运行的目录中除 2 个以外的所有最新文件,我使用:
cd /data
ls -1tr | head -n -2 | xargs -d '\n' rm -f --
我在登录到远程 Linux 机器后手动执行这些命令,但我试图将这些命令的登录和运行合并到一个命令中。
我使用登录位置执行类似的操作scp
并将文件 scp 到本地计算机的 dir /local/data
:
scp -i LightsailDefaultKey-eu-west-2.pem -r [email protected]:/data/ /local/data
有没有一种方法可以执行类似于上面的登录和命令的操作:
cd /data
ls -1tr | head -n -2 | xargs -d '\n' rm -f --
从本地计算机在远程计算机上以单个命令执行?
答案1
同意其他海报,您不应该用于ls
这种解析,但是由于您所拥有的适用于您正在做的事情,所以您不能在命令中使用 -d 开关ls
来获取完整的目录路径吗?
除非您要做更多工作,否则没有理由更改您的工作目录。请注意,您需要添加该通配符。
ssh user@host "ls -d1tr /data/* | head -n -2 | xargs -d '\n' rm -f --"
答案2
使用
find
而不是ls
.看为什么不是解析ls
(以及该怎么做)?。将要在远程系统上运行的命令用引号括起来(但请注意,嵌套引号可能会遇到困难)或放在此处的文档中。
例如使用 GNU 版本的find
、sort
、head
和cut
:
ssh -i LightsailDefaultKey-eu-west-2.pem [email protected] \
'find /data/ -maxdepth 1 -type f -printf "%Ts\t%p\0" | sort -z -nr |
head -z -n 2 | cut -z -f2 | xargs -0r rm -f --'
请注意,我在 printf 格式字符串周围使用了双引号,而不是单引号。这是因为它们嵌入在单引号中,包裹着 . 执行的整个命令管道ssh
。我本来可以使用-printf '\''%Cs\t%p\0'\''
,但是(因为这里不存在变量插值等风险)使用双引号更容易。
该-printf
格式打印文件的最后修改时间戳(自纪元以来的秒数,可以轻松地按 排序为数字sort -z -rn
)、制表符和文件的完整路径名。删除cut
时间戳和制表符,只留下文件名通过管道传输到xargs
.
另一种选择是使用特雷多克:
ssh -i LightsailDefaultKey-eu-west-2.pem [email protected] <<-'EOF'
find /data/ -maxdepth 1 -type f -printf '%Ts\t%p\0' | sort -z -nr |
head -z -n 2 | cut -z -f2 | xargs -0r rm -f --
EOF
答案3
据我所知,您不能scp
在同一执行中组合命令和 shell 命令。你能做的最好的事情是:
scp -i LightsailDefaultKey-eu-west-2.pem -r [email protected]:/data/ /local/data && \
ssh -i LightsailDefaultKey-eu-west-2.pem -r [email protected]:/data/ /local/data bash -c "cd /data; ls -1tr | head -n -2 | xargs -d '\n' rm -f --"
请注意,我用来&&
确保 ssh 不会运行,除非 scp 成功 - 否则,您将删除尚未同步的文件。