首页 > 解决方案 > 尽管文件名匹配,但用于检查文件是否存在的 Bash 命令不起作用

问题描述

我有以下脚本可以连接到 SFTP 服务器并删除与名称匹配的文件。但是,尽管服务器中存在具有匹配名称的文件,但脚本无法进入 -f 检查块,因此不会删除该文件。我在这里做错了什么?下面是我的脚本。

readarray partners < fileName.txt

for i in "${partners[@]}"
do
  file=`echo "ls" | sftp -i myKey myUser@myIP:${i} | grep "_Name_file_20181024"`
  echo $i
  echo $file

  if [[ -f $file ]]; then
    echo "********"
    delete=`echo "rm $file" | sftp -i myKey myUser@myIP:${i}`
    echo "********"
    echo $delete
  fi


done

我在我的 Mac 上运行它。任何帮助将非常感激。

标签: bashshellterminalscripting

解决方案


-f检查您的机器上是否存在文件。
我想您可以检查文件字符串是否为非空:

if [ -n "$file" ]; then

但是检查 grep 的结果会更可取:

if echo "ls" | sftp -i myKey "myUser@myIP:$i" | grep -q "_Name_file_20181024"; then

余数:

  • 反引号 ` 已弃用。用于$( ... )命令替换,允许嵌套(并且更具可读性)。
  • 总是引用你的变量。如果文件名有空格怎么办?
  • sftp只是ssh但只是文件传输。
  • 不要解析ls输出。这不好。ls是为了漂亮的格式化输出。

我会这样做,一次通过:

<fileName.txt xargs ssh -i myKey "myUser@myIP" rm -v -f

xargs会将每一行转换fileName.txt为单独的参数。或者readarray partners < fileName.txtssh .... rm -v -f "${partners[@]}"如果您没有 xargs,您也可以。将ssh运行一次(因此它会非常快)。如果您只是检查文件是否存在然后将其删除,那么如果最终结果是文件不存在,为什么还要检查呢?如果删除的文件不存在,该-f选项将不会失败,如果文件被删除,该选项将打印(因此您将知道哪些文件被删除)。rm-v

或者,如果您必须使用 sftp,这可能会起作用:

echo "rm -v -f $(<fileName.txt xargs printf "%q ")" |
sftp -i myKey myUser@myIP

但我不确定文件名中的特殊字符,所以我认为这需要一些调整。

如果您想从列表中过滤不存在​​的文件,我会这样做:

<fileName.txt ssh -i myKey "myUser@myIP" 'while IFS= read -r file; do [ -f "$file" ] && echo "$file"; done' 

IE。该while IFS= read -r部分是远程执行的,因此在删除服务器上检查文件是否存在。为所有工作执行单个 ssh 连接,然后为单个文件执行单独的 ssh 连接会更快。


推荐阅读