3

I'm sure there is a simple way to do this, but I am not finding it. What I want to do is execute a series of commands using lftp, and I want to avoid repeatedly connecting to the server if possible.

Basically, I have a file with a list full of ftp directories on the server. I want to connect to the server then execute something like the following: (assume at this point that I have already converted the text file into an array of lines using cat)

for f in "${myarray}"
do
cd $f;
nlist >> $f.txt;
cd ..;
done

Of course that doesn't work, but I have to imagine there is a simple solution to what I am trying to accomplish.

I am quite inexperienced when it comes to shell scripting. Any suggestions?

dgo
  • 3,877
  • 5
  • 34
  • 47

1 Answers1

6

First build a string that contains the list of lftp commands. Then call lftp, passing the command on its standard input. Lftp itself can redirect the output of a command to a file, with a syntax that resembles the shell.

list_commands=""
for dir in "${myarray[@]}"; do
  list_commands="$list_commands
  cd \"$dir\"
  nlist >\"$dir.txt\"
  cd .."
done

lftp <<EOF
open -u $username,$password $site
$list_commands
bye
EOF

Note that I assume that the directory names don't contain backslashes, single quotes or globbing characters. Add proper escaping if necessary.

By the way, to read lines from a file, see Why is while IFS= read used so often, instead of IFS=; while read..?. You might prefer to combine reading from the list of directories and building the commands:

list_commands=""
while IFS= read -r dir; do
  list_commands="$list_commands
  cd \"$dir\"
  nlist >\"$dir.txt\"
  cd .."
done <directory_list.txt
Community
  • 1
  • 1
Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
  • Thank you. This is exactly what I needed. There were some added complexities with line endings, because I (I didn't mention this) am working on a windows box ---> There were only two things about what you put that I think may be wrong (although it might be because of windows). I simply couldn't get it to work with directories that had spaces in the name - this won't be an issue at runtime, but it messed me up in testing. Also, I had to put double quotes after the = sign - where it says list_commands=$list_commands in order to get it to work. Definitely got me where I needed. Thank you! – dgo Aug 30 '12 at 21:09
  • @user1167442 That missing double quote was a typo, fixed. If you use `IFS=$'\r' instead of `IFS=`, the input file can have Windows line endings. Directories with a space should work (I think, I haven't tested), what went wrong? – Gilles 'SO- stop being evil' Aug 30 '12 at 21:24
  • I tried multiple variations of escaping and unescaping the double quotes around the variable as in: cd \"$dir\", but what happened both at the server and with the output was it read it as only the first part of the request - e.g cd "Folder D" was interpreted as cd "Folder" "D", and the output would be in file "Folder.txt" and "D.txt". However, I'm not too worried about it, because at runtime, it will only be working with capitalized unspaced strings, pre-escaped. Weird though. I handled the windows \r problem easy enough with tr -d "\r". Very handy. – dgo Aug 31 '12 at 02:09
  • I haven't quite had the stamina to grok the While IFS yet. I'll check it out though. Thanks for the informative answer. – dgo Aug 31 '12 at 02:10