我正在尝试列出一些ftp目录。我无法弄清楚如何使bash执行包含正确管道的命令。
这是我的剧本:
#/bin/sh
declare -a dirs=("/dir1" "/dir2") # ... and lots more
for d in "${dirs[@]}"
do
cmd='echo "ls /mydir/'"$d"'/*.tar*" | sftp -b - -i ~/mykey user@example.com 2>&1 | tail -n1'
$cmd
done
这只是输出:
"ls /mydir/dir1/*.tar*" | sftp -b - -i ~/mykey user@example.com 2>&1 | tail -n1
"ls /mydir/dir2/*.tar*" | sftp -b - -i ~/mykey user@example.com 2>&1 | tail -n1
如何让bash执行包括echo在内的整个字符串?我还需要能够解析命令的输出。
答案 0 :(得分:3)
我根本不认为您需要使用-b
开关。指定要作为字符串执行的命令应该足够了:
#/bin/bash
dirs=("/dir1" "/dir2")
for d in "${dirs[@]}"
do
printf -v d_str '%q' "$d"
sftp -i ~/mykey user@example.com "ls /mydir/$d_str/*.tar*" 2>&1 | tail -n1
done
正如comments中所建议的那样(感谢@Charles),我已使用printf
和%q
格式说明符来防止目录名称中可能被解释的字符由壳。
答案 1 :(得分:1)
不要将命令存储在字符串中;直接使用它。
#/bin/bash
declare -a dirs=("/dir1" "/dir2") # ... and lots more
for d in "${dirs[@]}"
do
echo "ls /mydir/$d/*.tar*" | sftp -b - -i ~/mykey user@example.com 2>&1 | tail -n1
done
通常,人们将命令存储在一个字符串中,这样他们就可以执行它并将其记录下来,作为一种误导形式的因子分解。 (我认为它不值得做正确的麻烦。)
请注意,sftp
默认从标准输入读取,因此您只需使用
echo "ls ..." | sftp -i ~/mykey user@example.com 2>&1 | tail -n1
您也可以使用here文档而不是管道。
sftp -i ~/mykey user@example.com 2>&1 <<EOF | tail -n1
ls /mydir/$d/*.tar.*
EOF
答案 2 :(得分:0)
首先,您需要使用/bin/bash
作为shebang来使用BASH数组。
然后删除echo并使用命令替换来捕获输出:
#/bin/bash
declare -a dirs=("/dir1" "/dir2") # ... and lots more
for d in "${dirs[@]}"
do
output=$(ls /mydir/"$d"/*.tar* | sftp -b - -i ~/mykey user@example.com 2>&1 | tail -n1)
echo "$output"
done
但我建议您不要在ls
命令中使用sftp
的输出。您可以将其替换为:
output=$(echo "/mydir/$d/"*.tar* | sftp -b - -i ~/mykey user@example.com 2>&1 | tail -n1)