Reputation: 7996
I'm trying to list some ftp directories. I can't work out how to make bash execute a command that contains pipes correctly.
Here's my script:
#/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 [email protected] 2>&1 | tail -n1'
$cmd
done
This just outputs:
"ls /mydir/dir1/*.tar*" | sftp -b - -i ~/mykey [email protected] 2>&1 | tail -n1
"ls /mydir/dir2/*.tar*" | sftp -b - -i ~/mykey [email protected] 2>&1 | tail -n1
How can I make bash execute the whole string including the echo? I also need to be able to parse the output of the command.
Upvotes: 2
Views: 4523
Reputation: 74695
I don't think that you need to be using the -b
switch at all. It should be sufficient to specify the commands that you would like to execute as a string:
#/bin/bash
dirs=("/dir1" "/dir2")
for d in "${dirs[@]}"
do
printf -v d_str '%q' "$d"
sftp -i ~/mykey [email protected] "ls /mydir/$d_str/*.tar*" 2>&1 | tail -n1
done
As suggested in the comments (thanks @Charles), I've used printf
with the %q
format specifier to protect against characters in the directory name that may be interpreted by the shell.
Upvotes: 3
Reputation: 532313
Don't store the command in a string; just use it directly.
#/bin/bash
declare -a dirs=("/dir1" "/dir2") # ... and lots more
for d in "${dirs[@]}"
do
echo "ls /mydir/$d/*.tar*" | sftp -b - -i ~/mykey [email protected] 2>&1 | tail -n1
done
Usually, people store the command in a string so they can both execute it and log it, as a misguided form of factoring. (I'm of the opinion that it's not worth the trouble required to do correctly.)
Note that sftp
reads from standard input by default, so you can just use
echo "ls ..." | sftp -i ~/mykey [email protected] 2>&1 | tail -n1
You can also use a here document instead of a pipeline.
sftp -i ~/mykey [email protected] 2>&1 <<EOF | tail -n1
ls /mydir/$d/*.tar.*
EOF
Upvotes: 1
Reputation: 786091
First you need to use /bin/bash
as shebang to use BASH arrays.
Then remove echo and use command substitution to capture the output:
#/bin/bash
declare -a dirs=("/dir1" "/dir2") # ... and lots more
for d in "${dirs[@]}"
do
output=$(ls /mydir/"$d"/*.tar* | sftp -b - -i ~/mykey [email protected] 2>&1 | tail -n1)
echo "$output"
done
I will however advise you not use ls
's output in sftp
command. You can replace that with:
output=$(echo "/mydir/$d/"*.tar* | sftp -b - -i ~/mykey [email protected] 2>&1 | tail -n1)
Upvotes: 1