检查远程计算机上是否存在文件名和/或路径中有空格的文件

All*_*lan 5 scripting bash string

我有一个简单的 bash 脚本;我基本上想确保该文件存在于远程机器上。我找到了许多关于如何执行此操作的示例,但缺少的组件是如何使用正在评估的路径和/或文件名中的空格执行此操作。

#!/bin/bash

HOST=server.local
DIR=/foo/bar
FILE="Foo Bar File With Spaces"


if ssh $HOST [[ -f ${DIR}/${FILE} ]]
then
   echo "The file exists"
else
   echo "The file doesn't exist."
fi
Run Code Online (Sandbox Code Playgroud)

所以,它失败了。它让我在条件表达式中出现语法错误。但是,如果我将 FILE 变量更改为:

FILE="Foo\ Bar\ File\ With\ Spaces"
Run Code Online (Sandbox Code Playgroud)

脚本工作(它找到文件,因为它在那里)。

我对我的条件表达式尝试了以下变体:

if ssh $HOST [[ -f "${DIR}/${FILE}" ]]
Run Code Online (Sandbox Code Playgroud)

if ssh $HOST [[ -f "${DIR}"/"${FILE}" ]]
Run Code Online (Sandbox Code Playgroud)

两者都不起作用;我知道我错过了一些简单的东西。有人可以指出我正确的方向吗?

ilk*_*chu 10

添加一对额外的引号,以便有一个用于本地 shell,一个用于运行的远程shell ssh

$ dir=/tmp; file="foo bar"; 
$ ssh somewhere ls -l "'$dir/$file'"
-rw-r--r-- 1 foo foo 4194304 Oct 19 18:05 /tmp/foo bar
$ ssh somewhere [[ -f  "'$dir/$file'" ]] ; echo $?
0
Run Code Online (Sandbox Code Playgroud)

您需要外部的双引号,以便本地 shell 在ssh命令运行之前扩展变量。内部有一个单引号,远程 shell 不会进一步扩展特殊字符。

除非文件名包含单引号,即。在这种情况下,您会遇到麻烦。

要解决这个问题,您需要向字符串添加必要的转义符。有些系统有printf "%q",新版本的 Bash 有${var@Q}扩展,应该做类似的事情。

$ dir=/tmp; file="\$foo' bar"
$ fullpath="$(printf "%q" "$dir/$file")"
$ ssh somewhere ls -l "$fullpath"
-rw-r--r-- 1 foo foo 0 Oct 19 18:45 /tmp/$foo' bar
Run Code Online (Sandbox Code Playgroud)